UITableViewCell在第一次加载的时候没有正确地包装文本,但是在屏幕上和屏幕上滚动的时候都没有

我正在关注使用具有dynamic高度的UITableViewCell从这个线程的答案。 这里是iOS7的GitHub解决scheme的链接 。

这个例子在iOS7中适用于我,但是当我在iOS6中运行它时,第一个单元格不能正确包装。

只有当我滚动屏幕的单元格,然后重新打开包装看起来是正确的。

这里是我的代码,通过我所做的任何更改以下评论,因此它可以在iOS6中运行

// *** Added/Removed for iOS6 

表格视图单元格

 #import "RJTableViewCell.h" #define kLabelHorizontalInsets 20.0f @interface RJTableViewCell () @property (nonatomic, assign) BOOL didSetupConstraints; @end @implementation RJTableViewCell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.titleLabel setLineBreakMode:NSLineBreakByTruncatingTail]; [self.titleLabel setNumberOfLines:1]; [self.titleLabel setTextAlignment:NSTextAlignmentLeft]; [self.titleLabel setTextColor:[UIColor blackColor]]; [self.titleLabel setBackgroundColor:[UIColor clearColor]]; self.bodyLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.bodyLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.bodyLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; [self.bodyLabel setLineBreakMode:NSLineBreakByTruncatingTail]; [self.bodyLabel setNumberOfLines:0]; [self.bodyLabel setTextAlignment:NSTextAlignmentLeft]; [self.bodyLabel setTextColor:[UIColor darkGrayColor]]; [self.bodyLabel setBackgroundColor:[UIColor clearColor]]; [self.contentView addSubview:self.titleLabel]; [self.contentView addSubview:self.bodyLabel]; [self updateFonts]; } return self; } - (void)updateConstraints { [super updateConstraints]; if (self.didSetupConstraints) return; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1.0f constant:kLabelHorizontalInsets]]; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:(kLabelHorizontalInsets / 2)]]; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:-kLabelHorizontalInsets]]; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.bodyLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1.0f constant:kLabelHorizontalInsets]]; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.bodyLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.titleLabel attribute:NSLayoutAttributeBottom multiplier:1.0f constant:(kLabelHorizontalInsets / 4)]]; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.bodyLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:-kLabelHorizontalInsets]]; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.bodyLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-(kLabelHorizontalInsets / 2)]]; self.didSetupConstraints = YES; } - (void)updateFonts { self.titleLabel2.font = [UIFont systemFontOfSize:16.0f]; // *** Added for iO6 self.bodyLabel.font = [UIFont systemFontOfSize:12.0f]; // *** Added for iO6 // self.titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; // *** Removed for iO6 // self.bodyLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption2]; // *** Removed for iO6 } 

表视图控制器

 #import "RJTableViewController.h" #import "RJModel.h" #import "RJTableViewCell.h" static NSString *CellIdentifier = @"CellIdentifier"; @interface RJTableViewController () @property (strong, nonatomic) RJModel *model; // This property is used to work around the constraint exception that is thrown if the // estimated row height for an inserted row is greater than the actual height for that row. // See: https://github.com/caoimghgin/TableViewCellWithAutoLayout/issues/6 @property (assign, nonatomic) BOOL isInsertingRow; @end @implementation RJTableViewController - (id)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self) { // Custom initialization self.title = @"Table View Controller"; self.model = [[RJModel alloc] init]; [self.model populateDataSource]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerClass:[RJTableViewCell class] forCellReuseIdentifier:CellIdentifier]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(clear:)]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addRow:)]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self.tableView reloadData]; // *** Added for iOS6 // *** Removed for iOS6 // [[NSNotificationCenter defaultCenter] addObserver:self // selector:@selector(contentSizeCategoryChanged:) // name:UIContentSizeCategoryDidChangeNotification // object:nil]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [self.tableView reloadData]; // *** Added for iOS6 // *** Removed for iOS6 // [[NSNotificationCenter defaultCenter] removeObserver:self // name:UIContentSizeCategoryDidChangeNotification // object:nil]; } - (void)contentSizeCategoryChanged:(NSNotification *)notification { [self.tableView reloadData]; } - (void)clear:(id)sender { NSMutableArray *rowsToDelete = [NSMutableArray new]; for (NSUInteger i = 0; i < [self.model.dataSource count]; i++) { [rowsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:0]]; } self.model = [[RJModel alloc] init]; [self.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView reloadData]; } - (void)addRow:(id)sender { [self.model addSingleItemToDataSource]; self.isInsertingRow = YES; NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:[self.model.dataSource count] - 1 inSection:0]; [self.tableView insertRowsAtIndexPaths:@[lastIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; self.isInsertingRow = NO; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.model.dataSource count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; [cell updateFonts]; NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row]; cell.titleLabel.text = [dataSourceItem valueForKey:@"title"]; cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"]; // Make sure the constraints have been added to this cell, since it may have just been created from scratch [cell setNeedsUpdateConstraints]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; [cell updateFonts]; NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row]; cell.titleLabel.text = [dataSourceItem valueForKey:@"title"]; cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"]; [cell setNeedsUpdateConstraints]; [cell updateConstraintsIfNeeded]; // Do the initial layout pass of the cell's contentView & subviews [cell.contentView setNeedsLayout]; [cell.contentView layoutIfNeeded]; // Since we have multi-line labels, set the preferredMaxLayoutWidth now that their width has been determined, // and then do a second layout pass so they can take on the correct height cell.bodyLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.bodyLabel.frame); [cell.contentView layoutIfNeeded]; CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; return height; } - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { if (self.isInsertingRow) { // A constraint exception will be thrown if the estimated row height for an inserted row is greater // than the actual height for that row. In order to work around this, we return the actual height // for the the row when inserting into the table view. // See: https://github.com/caoimghgin/TableViewCellWithAutoLayout/issues/6 return [self tableView:tableView heightForRowAtIndexPath:indexPath]; } else { return 500.0f; } } @end 

这是我所看到的,如果这是有用的前后 。

任何想法是怎么回事? 我很欣赏任何见解。

根据@Wain的build议,我试着将所有的代码从heightForRowAtIndexPath移动到cellForRowAtIndexPath并工作。 我想我需要设置cell.bodyLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.bodyLabel.frame)

我把所有的代码移动到“cellForRowAtIndexPath”,并有“heightForRowAtIndexPath”调用它现在得到的高度。 现在我不知道为什么在iOS7中,而不是在iOS6中,但我仍然搞清楚一些这种自动布局的东西。

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; [cell updateFonts]; NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row]; cell.titleLabel2.text = [dataSourceItem valueForKey:@"title"]; cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"]; [cell setNeedsUpdateConstraints]; [cell updateConstraintsIfNeeded]; // Do the initial layout pass of the cell's contentView & subviews [cell.contentView setNeedsLayout]; [cell.contentView layoutIfNeeded]; // Since we have multi-line labels, set the preferredMaxLayoutWidth now that their width has been determined, // and then do a second layout pass so they can take on the correct height cell.bodyLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.bodyLabel.frame); [cell.contentView layoutIfNeeded]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { RJTableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; return height; } 

对于其他人来到这个页面,使用你的面包有一些关于自动布局+ UITableViewCell的文章。

使用iOS 7和iOS 8 。

他的代码显示了如何使用原型单元来计算出高度,而不是每次都检查一次。 这将导致更快的代码。

通过覆盖layoutSubviews来设置preferredMaxLayoutWidth这意味着您不必在控制器中执行此操作。

 - (void)layoutSubviews { [super layoutSubviews]; [self.contentView layoutIfNeeded]; self.lineLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.lineLabel.frame); } 

[self.contentView layoutIfNeeded]在首次加载时获得正确的布局也很重要。