Swift Table View Static Cells by Code
Present Table View with Static Cells (Rows) Programmatically.
Scenario
Settings table view, constructed by Swift code with a minimal UI Storyboard, and presented with section headers and detail rows, linked to segues for navigation to individual views.
Audience
The article is for Swift developers who seek complete, integrated, code-centric solutions to speed up their development projects.
Model
We based the article on the AppsGym Books model app, which is published on Apple’s App Store (as 8Books). You can review the Settings page in the app and/or download the complete Xcode project on AppsGym.com, totally free.
UI
The Settings view menu shows a list of options/functions for user selection. The Settings table view utilises programmed section headers (Setup, Support, etc.) to group related records (e.g., Support: Info, Credits, Privacy, etc.) in a mini section within the overall list.
Books Settings sets up table view with a minimal Storyboard (image, and 1 prototype basic cell), while SettingsTableViewController.swift controls the layout and navigation.
Logic
- Declare variables for the arrays of sectionTitles (e.g., Support) and sectionContent (e.g. Info)
- Set up TableView sections, rows and cells, using sectionTitles and sectionContent
- Configure the cell in cellForRowAt(..), with each cell corresponding to a table row
- didSelectRowAt(..) will performSegues to navigate to the detailed views
Code
The Swift code snippets below are extracts from SettingsTableViewController.swift, which displays and controls the Settings page.
SettingsTableViewController.swift
class SettingsTableViewController: UITableViewController {
var sectionTitles = ["Setup", "Support"]
var sectionContent = [["iCloud", "Reset Data Integrity"],["Info","Credits","Privacy","Blog",]]
SettingsTableViewController.swift viewDidLoad()
//Large Titles for iOS 13/14
// Alternatively, check Storyboard NavigationBar 'PrefersLargeTitle'
if #available(iOS 13.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
} else {
// Fallback on earlier versions
}
tableView.delegate = self
tableView.dataSource = self
// remove bottom blank cells in the table view
tableView.tableFooterView = UIView(frame: CGRect.zero)
//iPad Layout: adds blank space to the left and right of the table view
tableView.cellLayoutMarginsFollowReadableWidth = true
// Remove text 'Settings' from back button
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
SettingsTableViewController.swift SECTION FUNCTIONS
override func numberOfSections(in tableView: UITableView) -> Int {
return sectionTitles.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return sectionContent[0].count // section 0 is the 1st/Top section 'Setup'
case 1:
return sectionContent[1].count // section 1 is the 2nd section 'Support'
// case 2:
// return sectionContent[2].count // section 2 is the 3rd section 'Socially Yours'
default:
return sectionContent[0].count
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionTitles[section] // section 0 is the 1st section
}
SettingsTableViewController.swift Cell Configuration
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
// Configure the cell...array of content within array of headers
cell.textLabel?.text = sectionContent[(indexPath as NSIndexPath).section][(indexPath as NSIndexPath).row]
var imageFileName:String!
switch (indexPath as NSIndexPath).section {
case 0: // Section 0 Setup
imageFileName = "Folder-Colored"
switch (indexPath as NSIndexPath).row {
case 0: imageFileName = "SettingsICloud"
case 1: imageFileName = "SettingsDataIntegrity"
default: imageFileName = "SettingsDefault"
}
case 1: // section 1 Support
switch (indexPath as NSIndexPath).row {
case 0: imageFileName = "SettingsAppInfo"
case 1: imageFileName = "SettingsCredits"
case 2: imageFileName = "SettingsPrivacy"
case 3: imageFileName = "SettingsBlog"
default: imageFileName = "SettingsDefault" }
default: break
}
cell.imageView?.image = UIImage(named: imageFileName)
return cell
}
SettingsTableViewController.swift didSelectRowAt()
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch (indexPath as NSIndexPath).section {
case 0: // Section 0 Setup
switch (indexPath as NSIndexPath).row {
case 0:
performSegue(withIdentifier: "showCloud", sender: self)
case 1:
performSegue(withIdentifier: "showDataIntegrityReset", sender: self)
default:
print(#function, "Error in Switch")
}
case 1: // section 1 Support
switch (indexPath as NSIndexPath).row {
case 0:
performSegue(withIdentifier: "showAppInfo", sender: self)
case 1:
performSegue(withIdentifier: "showCredits", sender: self)
case 2:
performSegue(withIdentifier: "showPrivacy", sender: self)
case 3:
performSegue(withIdentifier: "showBlog", sender: self)
default:
performSegue(withIdentifier: "showAppInfo", sender: self)
}
default: break
} //end switch
tableView.deselectRow(at: indexPath, animated: true)
}
} // end class