Auto layout of custom programmatic UITableViewCell fails upon scrolling

徘徊边缘 提交于 2020-01-13 18:30:25

问题


I'm trying to use the new auto layout capability of iOS 6 on a custom UITableViewCell which has been implemented programmatically. I added the addConstraint calls, and it works properly at first-- until I scroll. When I come back to the cell after scrolling the layout is trashed. By trashed I mean the margins between fields are all wrong (too large, well beyond the size of the cell). I'm speculating this has something to do with the dequeueReusableCellWithIdentifier method leaving me with a "dirty" cell, the same way you find yourself needing to reinitialize fields within cells, but I can't seem to do anything to coax it to render properly again. I've tried calling [self.contentView updateConstraints] before returning the cell. I've tried destroying the constraints and recreating them. Not only does it not work, but if it's attempted in layoutSubviews it freezes in an endless loop of some kind. Any ideas?

Here's the code to establish the constraints. It's located in 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]];

回答1:


I ran into this issue as well. If I wasn't dequeuing cells, everything seemed to work - scrolling, rotation etc. However, if I dequeued cells, then the layout started getting messed up. The only way I could get it to work was by overriding the cell's prepareForReuse method. In this method,

    1. remove all the custom subviews
    2. remove all constraints associated with those subviews from contentView
    3. add subviews and constraints again
-(void) prepareForReuse
{
    [self removeCustomSubviewsFromContentView];
    [self.contentView removeConstraints:self.constraints] //self.constraits holds all the added constraints
    [self setupSubviewsInContentView];
    [self addConstraintsToContentView];
}

If there is a better way to do this, I would love to learn as well :) I believe the advantage of dequeing is that the tableView does not have to hold a large number of cells in memory - but, with this method, one has to go through the cost of essentially setting up the cell everytime you dequeue.




回答2:


I had a similar problem, in case anyone is interested I've found a solution, see this question

What I've done:

- (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];
    }
}


来源:https://stackoverflow.com/questions/13854485/auto-layout-of-custom-programmatic-uitableviewcell-fails-upon-scrolling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!