在Swift中以编程方式创建UITableView

我尝试以编程方式实现UITableView而不使用xib或Storyboard。 这是我的代码:

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 } } 

但是当我运行应用程序时,我得到的只是空表。 在日志中,我看到几行sectionsrows ,但没有get cell 。 如何修复此代码以获取包含6行foo文本的表格?

注意:正如您所提到的,您刚开始使用Swift 3进行编程。 我以编程方式创建了一个tableView。 Copy代码CopypasteviewController运行项目…

 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 } } 

输出:

在此处输入图像描述

针对Swift 3进行了更新

选项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") } } 

选项2:使用此类替换选项1 TableViewController以上

 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 } } 

在此处输入图像描述

使用UITableViewController作为视图控制器表视图的数据源和委托是没有意义的。 您自己的视图控制器应该是表视图的数据源和委托。

由于您似乎希望视图控制器具有不占用整个视图的表视图,因此将所有内容移动到视图控制器,如下所示:

ViewController.swift:

 import UIKit class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { override func viewDidLoad() { super.viewDidLoad() let tableView: UITableView = UITableView() tableView.frame = CGRect(x: 10, y: 10, width: 100, height: 500) tableView.dataSource = self tableView.delegate = self self.view.addSubview(tableView) } func numberOfSectionsInTableView(tableView: UITableView) -> Int { NSLog("sections") return 2 } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { NSLog("rows") return 3 } 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 } } 

Swift 4兼容

您应该考虑创建UITableViewController并避免设置委托,而不是向UIViewController添加UITableView

 class YourTVC: TableViewController { override func viewDidLoad() { super.viewDidLoad() // setup stuff tableView.register(UITableViewCell.self, forCellReuseIdentifier: "yourCell") } // MARK: TableView override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 3 // set to value needed } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) cell.textLabel?.text = "Cell at row \(indexPath.row)" return cell } } 

您不需要为UITableView创建单独的类。 只需在您的ViewController类中实现UITableViewDelegate和UITableViewDataSource的协议,然后实现委托方法。 我认为你的代码应该是这样的

 class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource { 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) } 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 } } 

如果您仍然遇到问题,请告诉我们更多信息或显示日志。

我有类似的问题,因为数据不会填充我的程序化UITableView。 这是因为我使用的是没有强引用的委托/ dataSource。 一旦我保留了对它的引用(我有一个实现UITableViewDataSource和UITableViewDelegate的类),就会填充数据。