美文网首页Swift学习
Swift 踩坑笔记(二)—— 初始化Tableview 及自定

Swift 踩坑笔记(二)—— 初始化Tableview 及自定

作者: 黑羽肃霜 | 来源:发表于2018-08-06 23:00 被阅读622次

    综述

    旨在记录 自定义 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 方法永远都不会执行到

    相关文章

      网友评论

        本文标题:Swift 踩坑笔记(二)—— 初始化Tableview 及自定

        本文链接:https://www.haomeiwen.com/subject/fwsnvftx.html