I try to implement UITableView programmatically without use of xib or Storyboards. This is my code:
ViewController.swift
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let table: UITableViewController = MyTableViewController() let tableView: UITableView = UITableView() tableView.frame = CGRect(x: 10, y: 10, width: 100, height: 500) tableView.dataSource = table tableView.delegate = table self.view.addSubview(tableView) } }
MyTableViewController.swift
import UIKit class MyTableViewController: UITableViewController { override func numberOfSectionsInTableView(tableView: UITableView) -> Int { NSLog("sections") return 2 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { NSLog("rows") return 3 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { NSLog("get cell") let cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell") cell.textLabel!.text = "foo" return cell } }
But when I run app, all I get is empty table. In log I see a few lines of sections
and rows
, but no get cell
. How can I fix this code to get table with 6 lines of foo
text?
A view that presents data using rows in a single column. iOS 2.0+ iPadOS 2.0+ Mac Catalyst 13.1+ tvOS 9.0+
There are two main base ways to populate a tableview. The more popular is through Interface Building, using a prototype cell UI object. The other is strictly through code when you don't need a prototype cell from Interface Builder.
Table view presents data in multiple rows arranged in a single column, the cell design is fit as a row. However, collection view can create rows and columns, it can design cells in various ways, even if they are not necessarily rows. It's also the biggest feature of a collection view cell.
Note: As you mentioned you just started programming in Swift
. I created a tableView programmatically. Copy
and paste
below code into your viewController
and run the project...
import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private let myArray: NSArray = ["First","Second","Third"] private var myTableView: UITableView! override func viewDidLoad() { super.viewDidLoad() let barHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height let displayWidth: CGFloat = self.view.frame.width let displayHeight: CGFloat = self.view.frame.height myTableView = UITableView(frame: CGRect(x: 0, y: barHeight, width: displayWidth, height: displayHeight - barHeight)) myTableView.register(UITableViewCell.self, forCellReuseIdentifier: "MyCell") myTableView.dataSource = self myTableView.delegate = self self.view.addSubview(myTableView) } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print("Num: \(indexPath.row)") print("Value: \(myArray[indexPath.row])") } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath as IndexPath) cell.textLabel!.text = "\(myArray[indexPath.row])" return cell } }
Output:
Updated for Swift 3
Option 1:
import UIKit // // MARK :- TableViewController // class TableViewController: UITableViewController { private let headerId = "headerId" private let footerId = "footerId" private let cellId = "cellId" // // MARK :- HEADER // override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 150 } override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerId) as! CustomTableViewHeader return header } // // MARK :- FOOTER // override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { return 150 } override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerId) as! CustomTableViewFooter return footer } // // MARK :- CELL // override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 150 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! CustomTableCell return cell } override func viewDidLoad() { super.viewDidLoad() title = "TableView Demo" view.backgroundColor = .white setupTableView() } func setupTableView() { tableView.backgroundColor = .lightGray tableView.register(CustomTableViewHeader.self, forHeaderFooterViewReuseIdentifier: headerId) tableView.register(CustomTableViewFooter.self, forHeaderFooterViewReuseIdentifier: footerId) tableView.register(CustomTableCell.self, forCellReuseIdentifier: cellId) } } // // MARK :- HEADER // class CustomTableViewHeader: UITableViewHeaderFooterView { override init(reuseIdentifier: String?) { super.init(reuseIdentifier: reuseIdentifier) contentView.backgroundColor = .orange } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } // // MARK :- FOOTER // class CustomTableViewFooter: UITableViewHeaderFooterView { override init(reuseIdentifier: String?) { super.init(reuseIdentifier: reuseIdentifier) contentView.backgroundColor = .green } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } // // MARK :- CELL // class CustomTableCell: UITableViewCell { override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.backgroundColor = .white } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Option 2: replace above Option 1 TableViewController with this class
import UIKit // // MARK :- ViewController // class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private let headerId = "headerId" private let footerId = "footerId" private let cellId = "cellId" lazy var tableView: UITableView = { let tv = UITableView(frame: .zero, style: .plain) tv.translatesAutoresizingMaskIntoConstraints = false tv.backgroundColor = .lightGray tv.delegate = self tv.dataSource = self tv.register(CustomTableViewHeader.self, forHeaderFooterViewReuseIdentifier: self.headerId) tv.register(CustomTableViewFooter.self, forHeaderFooterViewReuseIdentifier: self.footerId) tv.register(CustomTableCell.self, forCellReuseIdentifier: self.cellId) return tv }() // // MARK :- HEADER // func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 150 } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerId) as! CustomTableViewHeader return header } // // MARK :- FOOTER // func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { return 150 } func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerId) as! CustomTableViewFooter return footer } // // MARK :- CELL // func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 150 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! CustomTableCell return cell } override func viewDidLoad() { super.viewDidLoad() title = "TableView Demo" view.backgroundColor = .white view.addSubview(tableView) setupAutoLayout() } func setupAutoLayout() { tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With