在Swift中使用以编程方式创build的UITableViewCell子类

我正在使用已经以编程方式创build的自定义单元格的表视图,没有使用IB。 我环顾四周,在NSChat问,但我仍然无法工作。 它只是显示默认的表格视图。 提前致谢!

EventCell.swift

import UIKit class EventCell: UITableViewCell { var eventName: UILabel = UILabel() var eventCity: UILabel = UILabel() var eventTime: UILabel = UILabel() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) self.contentView.addSubview(eventName) self.contentView.addSubview(eventCity) self.contentView.addSubview(eventTime) } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func layoutSubviews() { super.layoutSubviews() eventName = UILabel(frame: CGRectMake(20, 10, self.bounds.size.width - 40, 25)) eventCity = UILabel(frame: CGRectMake(0, 0, 0, 0)) eventTime = UILabel(frame: CGRectMake(0, 0, 0, 0)) } } 

ViewController.swift

 class ViewController: UITableViewController, UITableViewDelegate { var events: Dictionary<String, [String]> = ["0": ["Monroe Family", "La Cañada", "8:30"]] override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self; tableView.delegate = self; tableView.registerClass(EventCell.self, forCellReuseIdentifier: "EventCell") } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension; } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return events.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cellIdendifier: String = "EventCell" var cell: EventCell = tableView.dequeueReusableCellWithIdentifier(cellIdendifier, forIndexPath: indexPath) as EventCell cell = EventCell(style: .Default, reuseIdentifier: cellIdendifier) if let i = events[String(indexPath.row)] { cell.eventName.text = i[0] cell.eventCity.text = i[1] cell.eventTime.text = i[2] } cell.sizeToFit() return cell } } 

好的,首先几个重要的评论。

首先 ,每当表视图请求一个单元而不是重新使用旧的单元格时,您就不必要地创build了自己的新单元。 你应该删除这一行:

 cell = EventCell(style: .Default, reuseIdentifier: cellIdendifier) 

这是不必要的,因为出队将根据您为给定标识符注册的类自动创build新的单元格。

其次 ,在布置代码时,不应该使用主屏幕边界。 如果您的表格视图不是完整的宽度,这将打破。 相反,你可以使用self.bounds所以它总是相对于单元本身。

第三 ,你不应该调用setNeedsLayout或layoutIfNeeded,因为如果调用该方法,它已经布置了一切。

第四 ,你应该在设置表视图数据源之前注册你的表视图单元类,以防UITableView在数据源设置时开始从数据源请求事物。

第五 ,你的两个子视图的大小为0,0,所以它们不会出现。

如果这段代码确实运行时没有崩溃,那么您正在创buildEventCells,因为您正在通过dequeueReusableCellWithIdentifier:forIndexPath的结果进行强制转换。 这意味着你只是有一个布局/显示/数据问题。

我有同样的问题。 我在@ drewag的答案中应用了这个build议,但还有一些问题。 下面是一个简单的概念validation示例,演示如何使用以编程方式创build的UITableViewCell子类。

下面的图片是它应该看起来像。 黄色矩形是自定义单元格中的UILabel子视图。

在这里输入图像说明

这里是UITableViewCell子类。 它的工作是初始化单元格及其内容,添加子视图,并布置子视图。

 import UIKit class MyCustomCell: UITableViewCell { var myLabel = UILabel() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) myLabel.backgroundColor = UIColor.yellowColor() self.contentView.addSubview(myLabel) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func layoutSubviews() { super.layoutSubviews() myLabel.frame = CGRect(x: 20, y: 0, width: 70, height: 30) } } 

这是视图控制器代码。

 import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! let myArray = ["one", "two", "three", "four"] let cellReuseIdendifier = "cell" override func viewDidLoad() { super.viewDidLoad() tableView.registerClass(MyCustomCell.self, forCellReuseIdentifier: cellReuseIdendifier) tableView.dataSource = self tableView.delegate = self } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myArray.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdendifier, forIndexPath: indexPath) as! MyCustomCell cell.myLabel.text = myArray[indexPath.row] return cell } } 

笔记:

  • 我使用了一个普通的UIViewController而不是一个UITableViewController 。 如果您使用UITableViewController那么请移除UITableViewDelegateUITableViewDataSource协议引用,因为它们对于UITableViewController是多余的。 你也不需要@IBOutlet tableView行。
  • 在原始问题中find的主要问题行是eventName = UILabel(frame: CGRectMake(...)) 。 相反,它应该是eventName.frame = CGRect(...)

您的特定代码不起作用,因为它在EventCell.layoutSubviews中创build新的UILabel。 只有最初的UILabel被添加到视图树中,它们的大小可能是0。

我猜你想更新他们的帧,例如更新EventCell类的方法:

 override func layoutSubviews() { super.layoutSubviews() eventName.frame = CGRectMake(20, 10, self.bounds.size.width - 40, 25) eventCity.frame = CGRectMake(<actual size>) eventTime.frame = CGRectMake(<actual size>) } 

你可以在swift中使用懒惰的实例,以避免不得不放入layoutSubviews / view生命周期舞蹈。

 class EventCell: UITableViewCell { lazy public var lblName = { return UILabel (frame: CGRectMake(10, 0, self.bounds.size.width , 40)) }() lazy public var lblCity = { return UILabel (frame: CGRectMake(10, 40, self.bounds.size.width , 20)) }() lazy public var lblTime = { return UILabel (frame: CGRectMake(self.bounds.size.width - 80, 10, , 25)) }() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) self.contentView.addSubview(lblName) self.contentView.addSubview(lblCity) self.contentView.addSubview(lblTime) } }