为啥 UITableViewCell 初始化在 initWithCoder 中不起作用

Posted

技术标签:

【中文标题】为啥 UITableViewCell 初始化在 initWithCoder 中不起作用【英文标题】:Why is UITableViewCell initialization not working inside initWithCoder为什么 UITableViewCell 初始化在 initWithCoder 中不起作用 【发布时间】:2013-10-30 04:41:10 【问题描述】:

我正在尝试清理我的代码并使用 MVC 原则,方法是将尽可能多的与视图相关的内容推送到情节提要以及自定义 UIView 类中(即,而不是在 UIViewController 本身上执行与视图相关的内容)

所以我有一个自定义 UITableViewCell(称为CustomCell),它有几个属性,其中一个是我自己的label。因为我从情节提要加载单元格,所以我用initWithCoder 而不是initWithStyle:reuseIdentifier: 对其进行初始化,这就是我在CustomCell.m 中所拥有的,它是UITableViewCell 的子类(出于某种原因我想不通了解如何使用情节提要设置自定义字体..但这不是这个问题的重点):

// CustomCell.m - subclass of UITableViewCell
- (id)initWithCoder:(NSCoder *)aDecoder 
    self = [super initWithCoder:aDecoder];
    if (self) 
        NSLog(@"customizing cell font having text %@", self.label.text);
        UIFont *customFont = [UIFont fontWithName:@"Montserrat" size:16];
        self.label.textColor = [UIColor redColor];
        [self.label setFont:customFont];
    
    return self;

这根本行不通.. 日志语句为文本输出null,只是因为文本尚未加载。 self.label 也是 null (我不知道为什么我认为它现在应该从笔尖膨胀)但即使我在这里初始化它..它仍然无法工作。

所以我的解决方法是简单地将这个单元格自定义部分放在 TableViewController 中:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell 
forRowAtIndexPath:(NSIndexPath *)indexPath         
    UIFont *customFont = [UIFont fontWithName:@"Montserrat" size:16];
    [((CustomCell *)cell).label setFont:customFont];

它工作得很好..我对这种方法不满意,我想知道如何在CustomCell.m中让它工作

更新: 让事情变得更有趣.. 如果我将 UITableViewCell 属性的自定义代码放入 initWithCoder 中,它们就可以工作!考虑这个例子:

- (id)initWithCoder:(NSCoder *)aDecoder 
    self = [super initWithCoder:aDecoder];
    if (self) 
        UIView *bgColorView = [[UIView alloc] init];
        [bgColorView setBackgroundColor:[UIColor blueColor]];
        [self setSelectedBackgroundView:bgColorView];  // actually works!
    
    return self;

这让这更加奇怪。

【问题讨论】:

可能initWithCoder: 方法在后台线程上。尝试使用 performSelectorOnMainThread:withObject:waitUntilDone: 从另一种方法中原谅代码 使用 awakeFromNib 来初始化你的控件,我认为这是最好的函数,但它可以被多次调用。 @theShay 我的更新显示这与后台线程无关 所以试试awakeFromNibviewDidApper @theShay 细胞没有viewDidAppear: 方法。 【参考方案1】:

受andykkt的评论启发,我在awakeFromNib文档中找到了解释:

nib 加载基础架构向每个 从 nib 存档重新创建的对象,但仅在所有对象之后 存档已加载并初始化。当一个对象收到 一个 awakeFromNib 消息,它保证有它的所有出口和 动作连接已经建立。

这样就解释了上面的奇怪行为:initWithCoder 实例化了一个标准 UITableViewCell(已经预烘焙了 backgroundView 等).. 但是它仍然无法识别我添加到其中的网点通过情节提要.. awakeFromNib 确实如此。

【讨论】:

【参考方案2】:

我怀疑initWithCoder: 方法不会绘制单元格的内容,它只是初始化对象,并且正如您所注意到的,访问单元格的任何 ui 绘制方法实际上将单元格“绘制”到将您所做的更改应用于单元格。使用initWithNibName:bundle: 方法初始化UIViewController 时,您会看到相同的行为。

【讨论】:

以上是关于为啥 UITableViewCell 初始化在 initWithCoder 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UITableViewCell 相互重叠?

为啥手动重用的 UITableViewCell 在重新加载行时会消失?

调整 UITableViewCell 大小的 NSLayoutConstraint 错误

为啥我的自定义 UITableViewCell 在 cellForRowAtIndexPath 中为空?

为啥我的 UITableViewCell 的方向会改变 AutoLayout?

为啥 UITableViewCell 宽度小于 UITableView 宽度