Keywords: SwiftUI | List Separators | iOS Compatibility
Abstract: This article provides an in-depth exploration of methods to remove row separators from List components in SwiftUI, offering detailed implementations for iOS versions 13 through 15. It covers the official .listRowSeparator(.hidden) API introduced in iOS 15, analyzes the pros and cons of using LazyVStack as an alternative in iOS 14, and explains the technical details of UITableView-based customization for iOS 13. By comparing implementation differences across versions, the article serves as a comprehensive guide for developers to achieve separator removal while preserving other list styles.
Introduction
In SwiftUI development, the List component is essential for building data-driven interfaces, but its default row separator style may not align with specific design requirements. Developers often need to remove these separators while retaining other styles, such as padding and margins. Based on high-scoring Stack Overflow answers, this article systematically outlines solutions from iOS 13 to 15.
Official Solution for iOS 15
Apple introduced the .listRowSeparator modifier in iOS 15, which is the preferred method for removing separators. This API allows precise control over separator visibility by passing .hidden to hide lines. Example code:
List {
ForEach(items, id:\.self) {
Text("Row \($0)")
.listRowSeparator(.hidden)
}
}This approach only affects target rows without interfering with other list styles, and the code is concise and maintainable. Developers should note that this API is available only in iOS 15 and later; for apps supporting older versions, fallback solutions are necessary.
Alternative for iOS 14
In iOS 14, since SwiftUI's List is no longer fully backed by UITableView, traditional UIAppearance methods may fail. An effective alternative is using LazyVStack nested within a ScrollView. This mimics list scrolling while allowing full customization of separator styles. Example structure:
ScrollView {
LazyVStack {
ForEach(items, id:\.self) { item in
CustomRow(item: item)
.padding() // Manually add padding to maintain styles
}
}
}However, this requires manual handling of padding and margins, potentially increasing layout complexity. It is recommended for non-performance-critical scenarios, noting LazyVStack's lazy loading特性.
Low-Level Customization for iOS 13
For iOS 13, SwiftUI's List is implemented via UITableView, so separators can be removed by modifying UITableView appearance properties. Key steps include setting separatorStyle to .none to remove all separators and using tableFooterView to eliminate extra separators below the list. Example initialization code:
init() {
if #available(iOS 14.0, *) {
// iOS 14 does not show extra separators by default
} else {
UITableView.appearance().tableFooterView = UIView()
}
UITableView.appearance().separatorStyle = .none
}Note that this method affects all List instances in the app, which may cause style conflicts. It is advisable to apply it dynamically in onAppear and onDisappear to limit scope. Additionally, this approach may not work from iOS 14 onward, so use with version checks.
Other Reference Solutions
Beyond the main solutions, other answers mention setting separatorColor = .clear in iOS 13 to hide separators, but this also has global effects. Developers should prioritize version-specific APIs to ensure code robustness and maintainability.
Conclusion and Best Practices
Removing SwiftUI list row separators requires selecting appropriate solutions based on the target iOS version: use .listRowSeparator(.hidden) for iOS 15+; consider LazyVStack alternatives for iOS 14; and customize UITableView appearance for iOS 13. Use #available for version branching and test compatibility across devices. As SwiftUI evolves, official APIs may further simplify this task.