关于用Stroyboard 自定义 UITableViewCell 的一点讨论

如何自定义UITableViewCell:

本文不是教程,所以只简要描述一下步骤

  • 在 StoryBoard 里面绘制好UITableView 并在上面添加UITableViewCell 拖入你想要的控件。
  • 新建一个继承于UITableViewCell的类,然后为其添加IBOutlet和IBAction(Action也可以放到Controller中)
  • 在StoryBoard上修改Cell的Class,并与IBOutlet Action 建立好关联
  • 在IB中修改cell的identifier
  • 最后在TableView的DataSource里面用[tableView dequeueReusableCellWithIdentifier:key] 完成绘制

修改圆角等附加物

这是一个很让人纠结的问题。先说陷阱所在,如果直接从dequeueReusableCellWithIdentifier得来的cell修改layer的话,会出现一个问题,每一个条目都会调用此方法,于是每一个条目都会重新绘制圆角遮罩,从而无法适应用户手贱的高速滚动,明显能感到延迟和掉帧。

而正确做法,一般是把这个写在customCell的init里面,dequeueReusableCellWithIdentifier这里只为“模板”赋值。这样一次绘制即可。

但是上面的正确做法,仅仅适用于代码手写UI,而不适用Interface Builder。 为什么?因为Interface Builder生成的cell初始化的时候用的是initWithCoder, 但只绘制了边界,并没有绘制里面的东西,里面的东西只有到调用了dequeueReusableCellWithIdentifier才会开始绘制,所以如果你在initWithCoder里面输出IBOutlet的话,会发现全都是 NULL

那么应该怎么做?

和基友讨论了一下以及上网搜了一下,有两个做法。

  1. 本方法取自Ray的教程:原理就是,我既然不能获取到cell,那我先设置好一个View之后,把它当做SubView放到Cell上就是了。方法简单,只是又多了一个类

  2. 直接在Cell的DrawRect里面写绘制。这个理论上说是标准做法,但是不知道其他同学对DrawRect 难受不难受,毕竟这个方法类似于游戏里面的绘图主循环,每一帧都会调用一次的。这样每一帧都会重复劳动会不会觉得很难受,在浪费生产力。如果你要是搞竞赛出身的,会更难受。

  3. 一天过后发现了正确做法,awakeFromNib 这个方法。 但是iOS极度猥琐的把它藏在了 一个奇怪的头文件里面,并没有存在于UIView中。

    其实这是种误解,或者说,每帧都运行这是一个非常极端的情况,iOS不是傻逼,同样的纹理为什么要重复绘制?是这样的,如果用户没有给view设置isNeedDisplay 或者调整了view或者其subview的frame,drawRect是不会被触发的

Comments