Skip to main content

Struggling to hide the SwiftUI separators in a List or Form? 

 

The challenge

Creating the following form, separation lines appeared between NameLayout, FinalPhoto, RawPhoto, ApertureLayout and SubmitButton.

var body: some View {
    GeometryReader { geometry in
      Form {
        // layout elements
        NameLayout()
        FinalPhoto()
        RawPhoto()
        ApertureLayout()
        SubmitButton()
      }
    }
}

 

What was assessed

separatorStyle = .none

At first I tried adding a style none to remove all separators in the init()

UITableView.appearance().separatorStyle = .none

But no they didn't go away.

 

separatorColor = .clear

Changing the color of the separator to clear in the init()

UITableView.appearance().separatorColor = .clear

But no they didn't go away.

 

ViewModifier - Style

What about if I try a ViewModifier and managing the separator style for the actual element?

struct ListSeparatorStyle: ViewModifier {
  let style: UITableViewCell.SeparatorStyle
  func body(content: Content) -> some View {
    content
      .onAppear() {
        UITableView.appearance().separatorStyle = self.style
      }
  }
}

And to the View extension adding 

func listSeparatorStyle(style: UITableViewCell.SeparatorStyle) -> some View {
   ModifiedContent(content: self, modifier: ListSeparatorStyle(style: style))
}

Finally to the Form add the modifier

Form {
   // ... code ... //
}

.listSeparatorStyle(style: .none)

No - the separator line would not go away!

 

Success - they are gone

ViewModifier row separator

Adding a ViewModifier as in the above example, was a step in the right direction.  However, rather than editing the UITableView, something else was needed to be addressed.

In the ViewModiferExtension.swift file

struct HideRowSeparatorModifier: ViewModifier {
  static let defaultListRowHeight: CGFloat = 44

  var insets: EdgeInsets
  var background: Color

  init(insets: EdgeInsets, background: Color) {
    self.insets = insets
    var alpha: CGFloat = 0
    UIColor(background).getWhite(nil, alpha: &alpha)
    assert(alpha == 1, "Setting background to a non-opaque color will result in separators remaining visible.")
    self.background = background
  }


  func body(content: Content) -> some View {
    content
      .padding(insets)
      .frame(
        minWidth: 0, maxWidth: .infinity,
        minHeight: Self.defaultListRowHeight,
        alignment: .leading
      )
      .listRowInsets(EdgeInsets())
      .background(background)
  }
}

extension EdgeInsets {
  static let defaultListRowInsets = Self(top: 0, leading: 16, bottom: 0, trailing: 16)
}

 

Then in the ViewExtension.swift file add

func hideRowSeparator(
    insets: EdgeInsets = .defaultListRowInsets,
    background: Color = .white
  ) -> some View {
    modifier(HideRowSeparatorModifier(
      insets: insets,
      background: background
    ))
}

 

Now back to the form, all that you need to add is .hideRowSeparator().  Such as:

Form { 
  // layout elements 
  NameLayout()
    .hideRowSeparator()
  FinalPhoto()
    .hideRowSeparator()
  RawPhoto()
    .hideRowSeparator()
  ApertureLayout()
    .hideRowSeparator()
  SubmitButton()
}

Test and check... the separators should now be gone.

Related articles

Andrew Fletcher12 Aug 2022
Using SwiftUI URLComponent to change a URL's scheme
The challenge I was facing, I had written a script to scan barcodes and use Google book API to view the contents.  However, a snippet of the JSON response { "contentVersion": "0.2.0.0.preview.0", "panelizationSummary": { "containsEpubBubbles": false, ...
Andrew Fletcher12 Mar 2021
SwiftUI - custom navigation bar title
When managing a navigation title in Swift, you will have trodden down the path.  Previously you have entered something like .navigationTitle("Title") If you wanted to alter the font used for the navigation area, alter the init() in the view: struct YourView: View { //...