先上代碼
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 下面的代碼不能正確的執(zhí)行茎辐。
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIDForCodeCustomCell", for: indexPath) as! CodeCustomCell
// Configure the cell...
cell.configure(modelData: (modelData?[indexPath.row])!) // fatal error: unexpectedly found nil while unwrapping an Optional value
return cell
}
兩個錯誤:
1. fatal error: unexpectedly found nil while unwrapping an Optional value(一開始的錯誤注冊后解決)
2. 即使注冊了cell之后,View還是不能正確顯示我自己自定義的cell
上面的代碼不能正常工作祭阀。知道的是:
- dequeueReusableCell是為了系統(tǒng)為了提高效率的一個方法爱态。具體就是在緩沖池里面看下有沒有這個Cell衬潦。沒有的話再初始化它這樣回右。
- 后面的代碼運行沒有問題隆圆。
- 然后看了幾篇相關(guān)的文章。貌似意思是說dequeueReusableCell除了在緩沖池里面找東西還做了點別的翔烁?
- Swift中的構(gòu)造器解釋init和自定義cell的問題
- 《重寫prepareForReuse來重用UITableViewCell》-Cell重用的問題
引用下第一篇文章的話:
- 指定構(gòu)造器必須調(diào)用它直接父類的指定構(gòu)造器方法.
- 便利構(gòu)造器必須調(diào)用同一個類中定義的其它初始化方法.
- 便利構(gòu)造器在最后必須調(diào)用一個指定構(gòu)造器.
引用下《重寫prepareForReuse來重用UITableViewCell》的話:
重用cell的機制是利用緩沖池渺氧,將可重用的cell保存起來,顯示cell時蹬屹,先從緩沖池中取侣背,如果緩沖池中沒有此類的cell,也就是沒有可重用的cell慨默,此時就會重新初始化一份cell秃踩,并且加到緩沖池中。
最終問題得以解決业筏,涉及這幾個問題:
- 一個是Swift的幾個init構(gòu)造器的關(guān)系的問題上面的第4個就是對應(yīng)的解析
- 另一個就是官方文檔中強調(diào)的要注冊的問題。
貼上修改后的代碼鸟赫。
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(CodeCustomCell.self, forCellReuseIdentifier: "CellIDForCodeCustomCell")
// 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()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIDForCodeCustomCell", for: indexPath) as UITableViewCell
// Configure the cell...
(cell as! CodeCustomCell).configure(modelData: (modelData![indexPath.row])!)
return cell
}
class CodeCustomCell: UITableViewCell{
var _imageView:UIImageView!
var label1:UILabel!
var label2:UILabel!
var label3:UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
_imageView = UIImageView(frame: CGRect(x: 50, y: 0, width: 88, height: 88))
label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 42, height: 21))
label2 = UILabel(frame: CGRect(x: 0, y: 29, width: 42, height: 21))
label3 = UILabel(frame: CGRect(x: 0, y: 58, width: 42, height: 21))
}
func configure(modelData:ModelData){
label1.text = modelData.attr1
label2.text = modelData.attr2
label3.text = modelData.attr3
_imageView.image = UIImage(named: modelData.imageName)
self.addSubview(label1)
self.addSubview(label2)
self.addSubview(label3)
self.addSubview(_imageView)
}
required init?(coder aDecoder: NSCoder) {
// super.init(style: .default, reuseIdentifier: "CellIDForCodeCustomCell")
fatalError("init(coder:) has not been implemented")
}
}
順帶說說其他沒能正常顯示的原因:
- dataSource,delegate沒有設(shè)置
- storyBoard沒有和當(dāng)前TableViewController關(guān)聯(lián)
- storyBoard的cell的關(guān)聯(lián)可以寫也可以不寫的
- 沒有addSubView
最后附上自己分別用Storyboard文件蒜胖,xib文件消别,代碼直接定制3種方法定制自定義Cell的Demo鏈接
ThreeWaysToCustomYourCell