滚动时自定义编程UITableViewCell的自动布局失败

时间:2012-12-13 06:46:41

标签: xcode uitableview scroll autolayout

我正在尝试在自定义UITableViewCell上使用iOS 6的新自动布局功能,该功能已通过编程实现。我添加了addConstraint调用,它首先正常工作 - 直到我滚动。滚动后,当我回到单元格时,布局被删除。通过删除我的意思是字段之间的边距都是错误的(太大,远远超出单元格的大小)。我猜测这与dequeueReusableCellWithIdentifier方法有关,让我有一个“脏”单元格,就像你发现自己需要重新初始化单元格中的字段一样,但我似乎无法做任何事情来哄它正确渲染再次。我在尝试返回单元格之前尝试调用[self.contentView updateConstraints]。我试过破坏约束并重新创建它们。它不仅不起作用,而且如果在layoutSubviews中尝试它,它会在某种无限循环中冻结。有什么想法吗?

这是建立约束的代码。它位于initWithStyle:reuseIdentifier:

[self.completedLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.nextSetHeaderLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.nextSetDetailLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.youWillLearnHeaderLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.youWillLearnDetailLabel setTranslatesAutoresizingMaskIntoConstraints:NO];

[self.contentView removeConstraints:[self.contentView constraints]];

NSDictionary *views = NSDictionaryOfVariableBindings(_completedLabel, _nextSetHeaderLabel, _nextSetDetailLabel, _youWillLearnHeaderLabel, _youWillLearnDetailLabel);

[self.contentView addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-5-[_completedLabel]-5-|"
                                         options:0
                                         metrics:nil
                                           views:views]];
[self.contentView addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-5-[_nextSetHeaderLabel]-5-|"
                                         options:0
                                         metrics:nil
                                           views:views]];

[self.contentView addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-5-[_nextSetDetailLabel]-5-|"
                                         options:0
                                         metrics:nil
                                           views:views]];

[self.contentView addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-5-[_youWillLearnHeaderLabel]-5-|"
                                         options:0
                                         metrics:nil
                                           views:views]];

[self.contentView addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-5-[_youWillLearnDetailLabel]-4-|"
                                         options:0
                                         metrics:nil
                                           views:views]];

[self.contentView addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-5-[_completedLabel]-12-[_nextSetHeaderLabel]-0-[_nextSetDetailLabel]-12-[_youWillLearnHeaderLabel]-0-[_youWillLearnDetailLabel(>=20)]-1-|"
                                         options:0
                                         metrics:nil
                                           views:views]];

2 个答案:

答案 0 :(得分:1)

我也遇到了这个问题。如果我没有将单元格出列,那么一切似乎都有效 - 滚动,旋转等。但是,如果我将单元格出列,那么布局就会变得混乱。我能让它工作的唯一方法是重写单元格的prepareForReuse方法。在这种方法中,

    1.删​​除所有自定义子视图
    2.从contentView中删除与这些子视图关联的所有约束 3.再次添加子视图和约束
    -(void) prepareForReuse
    {
        [self removeCustomSubviewsFromContentView];
        [self.contentView removeConstraints:self.constraints] //self.constraits holds all the added constraints
        [self setupSubviewsInContentView];
        [self addConstraintsToContentView];
    }
    

    如果有更好的方法可以做到这一点,我也很乐意学习:)我相信dequeing的优点是tableView不必在内存中保存大量的单元格 - 但是,使用这种方法每次出列时,都必须承担基本上设置单元格的费用。

答案 1 :(得分:0)

我有类似的问题,如果有人有兴趣我找到了解决方案,请参阅此question

我做了什么:

- (void)awakeFromNib
{
    [super awakeFromNib];

    for (NSLayoutConstraint *cellConstraint in self.constraints)
    {
        [self removeConstraint:cellConstraint];

        id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;
        id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;

        NSLayoutConstraint* contentViewConstraint = [NSLayoutConstraint constraintWithItem:firstItem
                                                                                 attribute:cellConstraint.firstAttribute
                                                                                 relatedBy:cellConstraint.relation
                                                                                    toItem:seccondItem
                                                                                 attribute:cellConstraint.secondAttribute
                                                                                multiplier:cellConstraint.multiplier
                                                                                  constant:cellConstraint.constant];

        [self.contentView addConstraint:contentViewConstraint];
    }
}