Removing List’s cell separators in SwiftUI

Currently, as of Xcode 11.1, Apple provides no way for developers to specify a cell separator style for SwiftUI’s List.

Having run into this issue myself, I finally stumbled upon a workaround:

UITableView.appearance().separatorStyle = .none

List seems to respect the UITableView appearance proxy. While this may change in future iOS releases, it’s a good enough solution for the time being.

There is one major caveat - UITableView.appearance() affects the appearance of all Lists in the application. How can we restrict our desired appearance to a single screen?

We utilize a view’s lifecycle events, View.onAppear and View.onDisappear, to set and then unset our custom appearance for a given view.

List {
    Text("a")
    Text("b")
    Text("c")
    Text("d")
}.onAppear {
    UITableView.appearance().separatorStyle = .none
}.onDisappear {
    UITableView.appearance().separatorStyle = .singleLine
}

While this works, it seems rather unwieldly and odd. We can further simplify this code by wrapping part of it in a ViewModifier.

public struct ListSeparatorStyleNoneModifier: ViewModifier {
    public func body(content: Content) -> some View {
        content.onAppear {
            UITableView.appearance().separatorStyle = .none
        }.onDisappear {
            UITableView.appearance().separatorStyle = .singleLine
        }
    }
}

extension View {
    public func listSeparatorStyleNone() -> some View {
        modifier(ListSeparatorStyleNoneModifier())
    }
}

As you can see, we’ve wrapped our appearance setting code into a neat little view modifier. Our example can now be reduced to:

List {
    Text("a")
    Text("b")
    Text("c")
    Text("d")
}.listSeparatorStyleNone()

Note: There is still one issue that we haven’t solved. While view lifecycle events allow us to set/unset the appearance, they affect all views in a given screen. The subject of our modifier must be destroyed for the appearance to restore to its original state, and thus we cannot prevent it from affecting sibling views. We will tackle this problem in a future post.

 
81
Kudos
 
81
Kudos

Now read this

Fixing NSManagedObject’s ObservableObject conformance

In working with SwiftUI you may have noticed that NSManagedObject is not a particularly correct implementation of ObservableObject. Your NSManagedObject does not publish changes when any of its @NSManaged properties are mutated. There’s... Continue →