Note that there are some explanatory texts on larger screens.

plurals
  1. POAutoLayout not pinning subview to superview
    primarykey
    data
    text
    <p>I'm trying to pin a subview inside of a custom <code>UITableViewCell</code> class to the left side of the cell's <code>contentView</code>. I'm adding the subview to the <code>contentView</code> inside of the <code>initWithStyle</code> method of the subclass, as well as adding constraints inside of that method. Unfortunately, I have two problems:</p> <ol> <li><p>The subview is not pinning to the left edge of the <code>contentView</code> even though I'm using the following code to do so:</p> <pre><code>[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_animatedView]-[_aTextField][_rightImageView]|" options:NSLayoutFormatDirectionLeftToRight metrics:nil views:viewDictionary]]; </code></pre> <p>To me, that format string should be pinning the <code>_animatedView</code> to the left side of the <code>contentView</code>, and then appending the other subsequent views as close as possible afterwards. Instead, all three views show up together in the proper order in the middle of the <code>contentView</code>, instead of at the left edge. I'm new to using autolayout, so this might be a confusion of how the format strings work on my part.</p></li> <li><p><strong>Solved</strong>: Thanks to Guillaume's suggestion, I was able to do a little bit of testing and find out that the reason that the cell contents were wildly displaced as I scrolled through the table was that I had not overridden the <code>UITableViewCell</code> method, <code>prepareForReuse</code>. This method is called when a <code>UITableViewCell</code> is prepared to be reused to display information for another object in the <code>UITableView</code>, which incidentally happens when scrolling occurs. The solution was as simple as inserting the following code into my <code>UITableViewCell</code> subclass:</p> <pre><code>-(void) prepareForReuse { [self setNeedsUpdateConstraints]; } </code></pre></li> </ol> <p>The other problem is that the constraints appear to not be enforced until I select a row of the TableView where the custom cells are being used. Is there a place other than <code>initWithStyle</code> I should be setting up the constraints or is this a different issue?</p> <p>Update:</p> <p><strong>CustomTableCell.m</strong> </p> <pre><code>@interface ListTableCell () { NSDictionary *_viewsForConstraints; // Used inside updateConstraints method. NSArray *_animatedViewSizeConstraints; NSArray *_centeringConstraints; NSArray *_horizontalConstraints; } @end - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Set up the cell elements. self.contentView.translatesAutoresizingMaskIntoConstraints = NO; self.animatedView = [[AnimatedView alloc] initWithFrame:CGRectZero]; self.animatedView.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview:self.animatedView]; self.aTextField = [[UITextField alloc] initWithFrame:CGRectZero]; self.aTextField.textColor = [UIColor whiteColor]; self.aTextField.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview:self.aTextField]; self.rightImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; self.rightImageView.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview:self.rightImageView]; _viewForConstraints = NSDictionaryOfVariableBindings(_animatedView, _aTextField, _rightImageView); // Add height/width constraints to the animated view. NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.animatedView attribute:NSLayoutAttributeHeight relatedBy:0 toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:self.contentView.frame.size.height]; NSLayoutConstraint *aspectRatioConstraint = [NSLayoutConstraint constraintWithItem:self.animatedView attribute:NSLayoutAttributeHeight relatedBy:0 toItem:self.animatedview attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]; _animatedViewSizeConstraints = @[heightConstraint, aspectRatioConstraint]; // Center elements vertically. NSLayoutConstraint *animatedViewVerticalCenterConstraint = [NSLayoutConstraint constraintWithItem:self.animatedView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]; NSLayoutConstraint *aTextFieldVerticalCenterConstraint = [NSLayoutConstraint constraintWithItem:self.aTextField attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]; NSLayoutConstraint *rightImageVerticalCenterConstraint = [NSLayoutConstraint constraintWithItem:self.rightImageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]; _centeringConstraints = @[animatedViewVerticalCenterConstraint, aTextFieldVerticalCenterConstraint, rightImageVerticalCenterConstraint]; _horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|[_animatedView]-[_aTextField][_rightImageView]|" options:NSLayoutFormatDirectionLeftToRight metrics:nil views:viewDictionary]]; self.backgroundColor = [UIColor greenColor]; self.editingAccessoryType = UITableViewCellAccessoryNone; self.accessoryType = UITableViewCellAccessoryNone; self.selectionStyle = UITableViewCellSelectionStyleNone; self.aTextField.userInteractionEnabled = NO; [self setNeedsUpdateConstraints]; } -(void) updateConstraints { [super updateConstraints]; [self.contentView addConstraints:_animatedViewSizeConstraints]; [self.contentView addConstraints:_centeringConstraints]; [self.contentView addConstraints:_horizontalConstraints]; } </code></pre> <p><strong>TableViewController.m</strong></p> <pre><code> - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; CustomTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; // Configure the cell. cell.aTextField.text = @"Test Text"; cell.aTextField.delegate = self; return cell; } </code></pre> <p>I can confirm that <code>initWithStyle</code> is getting called because the background is always green and subviews always show up, they just show up very oddly spaced initially.</p> <p>Thank you for any help with this!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload