An elegant way to layout a static table using Swift enum.
Chaos in your setting view controller code? Try enum.
Install cocoapods if you have not. Then add this line to your podfile:
pod 'EnumeratedTable', '~> 0.0.6'
First make sure you are using Xcode 11.0 or later.
Then, go to File -> Swift Packages -> Add Package Dependency...
First of all, consider the Example project in this repository a best practice.
extension ViewController: TableEnumerated {
// ...
}
extension ViewController: TableEnumerated {
enum Section: Int, SectionEnumeration {
case user
case setting
}
}
extension ViewController: TableEnumerated {
enum UserRow: Int, RowEnumeration {
case avatar
case biography
var text: String? {
switch self {
case .avatar:
return "iMoe"
case .biography:
return "A developer."
}
}
var reuseIdentifier: String? {
switch self {
case .avatar:
return "Avatar Cell"
case .biography:
return "Cell"
}
}
}
enum RichTextRow: Int, RowEnumeration {
case row1
case row2
var text: String? {
switch self {
case .row1:
return "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
case .row2:
return "Ut enim ad minim veniam."
}
}
var reuseIdentifier: String? {
return "Rich Cell"
}
}
enum Section: Int, SectionEnumeration {
case user
case setting
var RowsInSection: RowEnumerated.Type {
switch self {
case .user:
return ViewController.UserRow.self
case .setting:
return ViewController.RichTextRow.self
}
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return numberOfEnumeratedSections
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberOfEnumeratedRows(in: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return enumeratedCell(at: indexPath, inside: tableView)
}
}
enum SelectableRow: Int, RowEnumeration {
case about
case githubRepo
var text: String? {
switch self {
case .about:
return "About EnumeratedTable"
case .githubRepo:
return "GitHub Repository"
}
}
var height: CGFloat? {
return 56
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return enumeratedRow(at: indexPath)?.height ?? UITableView.automaticDimension
}
As default, you can provide text, detail (fits in the detail label of a UITableViewCell instance) and height.
But since enumerations are enum
(of course), you can provide whatever value you want.
extension ViewController: TableEnumerated {
// ...
enum RichTextRow: Int, RowEnumeration {
case row1
case row2
var text: String? {
switch self {
case .row1:
return "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
case .row2:
return "Ut enim ad minim veniam."
}
}
var headline: String {
switch self {
case .row1:
return "Row 1"
case .row2:
return "Row 2"
}
}
var subhead: String {
switch self {
case .row1:
return "Subhead 1"
case .row2:
return "Subhead 2"
}
}
}
// ...
}
extension RichTextTableViewCell: Enumerable {
func configure(using enumerated: RowEnumerated) {
let enumerated = enumerated as! ViewController.RichTextRow
headlineLabel.text = enumerated.headline
subheadLabel.text = enumerated.subhead
bodyLabel.text = enumerated.text
}
}
extension AvatarTableViewCell: Enumerable {
func configure(using enumerated: RowEnumerated) {
let enumerated = enumerated as! ViewController.UserRow
nameLabel.text = enumerated.text
avatarImageView.image = enumerated.image
}
}
extension ViewController: TableEnumerated {
// ...
enum SelectableRow: Int, RowEnumeration {
case about
case githubRepo
func handleSelection(by viewController: UIViewController) {
switch self {
case .about:
viewController.performSegue(withIdentifier: "Show About", sender: nil)
case .githubRepo:
let url = URL(string: "https://github.com/EdgarDegas/EnumeratedTable")!
let safariViewController = SFSafariViewController(url: url)
viewController.present(safariViewController, animated: true)
}
}
}
// ...
}
extension ViewController: UITableViewDelegate {
// ...
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
handleSelection(at: indexPath, by: self)
}
// ...
}