Skip to content

Instantly share code, notes, and snippets.

@djryanash
Created May 15, 2023 05:38
Show Gist options
  • Save djryanash/b3d0f360c50b020d82119316b47a766f to your computer and use it in GitHub Desktop.
Save djryanash/b3d0f360c50b020d82119316b47a766f to your computer and use it in GitHub Desktop.
Generic UITableView with Headers
import UIKit
class ViewController: UIViewController {
var hasSearched: Bool = false
let peopleArray = [
//["primaryImage", "personNext", "personJobTitle", "selectedImage", "section"],
["dollarsign.circle", "Ben Shapiro", "Accounts Manager", "dollarsign.circle.fill", "Core Team"],
["hammer.circle", "Robert Bokelman", "Operations Manager", "hammer.circle.fill", "Supplemental Team"],
["phone.connection", "Sandra Berman", "External Comms", "phone.connection.fill", "Supplemental Team"],
["key", "Nicolas Sarcozy", "President", "key.fill", "Core Team"],
["person", "Hillary Tate", "Marketing Manager", "person.fill", "Core Team"],
["paperplane", "Florence Wong", "Design and Execution", "paperplane.fill", "Core Team"],
["doc.badge.gearshape", "Indira Mohamed", "Research and Development", "doc.badge.gearshape.fill", "Core Team"],
["person.3", "Philipous Angelos", "International Relations", "person.3.fill", "Core Team"],
["alarm.waves.left.and.right", "Simon Graham", "Sales Manager", "alarm.waves.left.and.right.fill", "Core Team"],
["cloud.rain", "Tamara Westinghouse", "Environmental Impact", "cloud.rain.fill", "Supplemental Team"],
["baseball", "personNext", "personJobTitle", "baseball.fill", "section"],
["graduationcap", "personNext", "personJobTitle", "selectedImage", "graduationcap.fill"],
["trophy", "personNext", "personJobTitle", "selectedImage", "trophy.fill"],
["megaphone", "Forrest Gump", "personJobTitle", "selectedImage", "megaphone.fill"],
]
let sectionsArray = ["Core Team", "Supplemental Team"]
let tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.backgroundView = UIView(frame: tableView.bounds)
tableView.backgroundView?.backgroundColor = .systemGray5
tableView.allowsMultipleSelection = true
tableView.layer.cornerRadius = 20
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.register(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "header")
return tableView }()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .systemGray6
self.tableView.dataSource = self
self.view.addSubview(tableView)
self.tableView.delegate = self
self.tableViewConfigure() }
private func tableViewConfigure() {
self.tableView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -10).isActive = true
self.tableView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 10).isActive = true
self.tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
self.tableView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true }
override func viewDidLayoutSubviews() {
if let rowHeight = self.tableView.cellForRow(at: [0,0])?.contentView.frame.height {
let numberOfRows = self.tableView.numberOfRows(inSection: 0)
self.tableView.heightAnchor.constraint(equalToConstant: CGFloat(rowHeight) * CGFloat(numberOfRows))
.isActive = true
self.tableView.isScrollEnabled = false }
else { self.tableView.heightAnchor.constraint(equalToConstant: 540).isActive = true } }
func getSections(with array: [[String]]) -> [String] {
var sections: [String] = []
for i in 0..<peopleArray.count {
if !sections.contains(peopleArray[i].last!) {
sections.append(peopleArray[i].last!) } }
return sections }
func getRowsInSections(with array: [[String]]) {
if !hasSearched {
var coreTeam = 0
var supTeam = 0
for item in array {
if item.last!.contains("Supplemental Team") { supTeam += 1 }
else { coreTeam += 1 } } }
hasSearched = true }
func setCell(with cell: UITableViewCell, cellForRowAt indexPath: IndexPath, column: Int) -> UITableViewCell? {
let sectionName = getSections(with: peopleArray)[indexPath.section]
let sectionItems = peopleArray.filter { $0.last == sectionName }
let item = sectionItems[indexPath.row]
var content = cell.defaultContentConfiguration()
content.image = UIImage(systemName: item[column])
content.text = item[1]
content.secondaryText = item[2]
cell.contentConfiguration = content
return cell }
func checkMemoryUsage<R>(_ thingToCheck: R, name: String = #function) {
// You can pass in almost anything - a variable/constant/struct/class/function etc.
let size = MemoryLayout.size(ofValue: thingToCheck)
let stride = MemoryLayout.stride(ofValue: thingToCheck)
let alignment = MemoryLayout.alignment(ofValue: thingToCheck)
print("\(name).size: \(size)")
print("\(#function)).stride: \(stride)")
print("\(type(of: thingToCheck)).alignment: \(alignment)") }
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var sections = self.getSections(with: peopleArray )
if section < sections.count {
let sectionName = sections[section]
return peopleArray.filter { $0.last == sectionName }.count }
return 0 }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
return setCell(with: cell, cellForRowAt: indexPath, column: 0) ?? UITableViewCell() }
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.isSelected == true {
let cell = tableView.cellForRow(at: indexPath)!
cell.selectionStyle = .none
_ = setCell(with: cell, cellForRowAt: indexPath, column: 3) } }
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.isSelected == false {
let cell = tableView.cellForRow(at: indexPath)!
_ = setCell(with: cell, cellForRowAt: indexPath, column: 0) } }
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.getSections(with: peopleArray)[section] }
func numberOfSections(in tableView: UITableView) -> Int {
self.getSections(with: peopleArray).count }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment