综述
旨在记录 自定义 tableviewCell
搭配 tableview
初始化的正确方法
坑点
我们在 OC 中的 cellForRowAtIndexPath
去初始化一个自定义tableviewCell
的时候,有两种方式:
- 方法一:在初始化
tableview
的时候就去register
这个自顶一个的cell
, 这种写法在cellForRowAtIndexPath
部分就不用去判断这个cell
是否非空。因为以前写 OC 都不用这种方法,这里就不赘述 - 方法二:是直接在
cellForRowAtIndexPath
去初始化,为了继续下面的讨论,这里再摘抄一次:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *const OptionTableReuseID = @"reuseID"; //设立reuse池的标签名(或者说池子的名称) //表示从现有的池子(标签已指定)取出排在队列最前面的那个 cell UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:OptionTableReuseID]; NSLog(@"cell = %@",cell.textLabel.text); //如果为空,表示池子里并没有创建过可用来reuse的cell,就表示这是个新的cell,那么就创建一个cell并放到池子里用于后续可能的reuse if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:OptionTableReuseID]; NSLog(@"New cell = %@",cell.textLabel.text); } else{ NSLog(@"Reused cell = %@",cell.textLabel.text);//为了调试好看,正常并不需要else } //从数组中取出对应的文本,贴给当前的这个cell,index是随着回滚事件代理调用的对应路径 cell.textLabel.text = self.MyList[indexPath.row]; NSLog(@"row = %lu ",indexPath.row); return cell; }
问题就在于,在Swift
中用第二种方法,就会报错。
问题一:
旨在复习两种使用dequeueReuseableCellWithIdentifier
的方法自定义UITableViewCell中注册cell及reuseID的使用
- 使用
dequeueReuseableCellWithIdentifier:
可不注册,但是必须对获取回来的cell进行判断是否为空,若空则手动创建新的cell; - 使用
dequeueReuseableCellWithIdentifier:forIndexPath:
必须注册,但返回的cell可省略空值判断的步骤。
下面是注册cell
的方法
//初始化 _tableview 之后去注册自定义cell DialogSubViewLanCell
_tableview.register(DialogSubViewLanCell.self, forCellReuseIdentifier: languageCellId)
这里 DialogSubViewLanCell.self 其实就是OC 中的 [DialogSubViewLanCell class]
问题二
我们先来看正确的代码,再讨论问题二
// cellForRowAtIndexPath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = (tableView.dequeueReusableCell(withIdentifier: languageCellId, for: indexPath)) as! DialogSubViewLanCell
cell._titleLabel.text = _languages[indexPath.row]
return cell
}
// 自定义 Cell
class DialogSubViewLanCell: UITableViewCell {
var _titleLabel: UILabel
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
_titleLabel = UILabel.init(frame: CGRect.zero)
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
configTitleUI()
}
private func configTitleUI() {
_titleLabel.text = "aaa"
self.addSubview(_titleLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
正常情况下,我们会在自定义的cell
中定义一个新的初始化方法。
但是不管使用(tableView.dequeueReusableCell(withIdentifier: languageCellId, for: indexPath)) as! DialogSubViewLanCell
还是使用 (tableView.dequeueReusableCell(withIdentifier: languageCellId)) as! DialogSubViewLanCell
执行的时候,代码就很自然的去执行了 DialogSubViewLanCell
默认的init()
方法而不会执行我们自定义的init
方法
if cell == nil { DialogSubViewLanCell.init(someModels)}
因为已经执行了init()
,导致自定义的init
方法永远都不会执行到
网友评论