如何以编程方式使用AutoLayout创build自定义UITableViewCell

我试图实现一个UITableView,其行为与Twitter客户端的时间轴类似。 现在我只是试图在UITableViewCell中获取两个标签。 正如这个堆栈溢出的答案所build议的,我为每个布局使用了不同的reuseIdentifier。 我的布局很简单,包括一个标签或两个标签。 最后,我将调整UITableViewCells的高度,但首先我需要获取与内容填充单元格。

如果我用initWithFrame:设置它们的框架,我可以得到如此显示的标签initWithFrame:但是约束没有被实现。

  • 问题:什么是防止标签和约束出现? 我在我的UITableViewCell实现中显然缺less一些东西,但我不知道它是什么。

  • 第二个问题:我正在为viewDidLoad每个reuseIdentifier正确注册UITableViewCell类?

这可能会遇到困难,但Interface Builder混淆了我,我想在代码中完成这一切。

以下是名为TVTCell.h的自定义UITableViewCell的代码:

 static NSString * const kCellIDTitle = @"CellWithTitle"; static NSString * const kCellIDTitleMain = @"CellWithTitleMain"; @interface TVTCell : UITableViewCell { NSString *reuseID; } @property (nonatomic, strong) UILabel *nameLabel; @property (nonatomic, strong) UILabel *mainLabel; @end 

和TVTCell.m:

 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { reuseID = reuseIdentifier; nameLabel = [[UILabel alloc] init]; [nameLabel setTextColor:[UIColor blackColor]]; [nameLabel setBackgroundColor:[UIColor colorWithHue:32 saturation:100 brightness:63 alpha:1]]; [nameLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; [nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.contentView addSubview:nameLabel]; mainLabel = [[UILabel alloc] init]; [mainLabel setTextColor:[UIColor blackColor]]; [mainLabel setBackgroundColor:[UIColor colorWithHue:66 saturation:100 brightness:63 alpha:1]]; [mainLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; [mainLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.contentView addSubview:mainLabel]; [self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO]; } return self; } - (void)updateConstraints { [super updateConstraints]; NSDictionary *views = NSDictionaryOfVariableBindings(nameLabel, mainLabel); if (reuseID == kCellIDTitle) { NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" options: NSLayoutFormatAlignAllCenterX metrics:nil views:views]; [self.contentView addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel]|" options: NSLayoutFormatAlignAllCenterX metrics:nil views:views]; [self.contentView addConstraints:constraints]; } if (reuseID == kCellIDTitleMain) { NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" options: NSLayoutFormatAlignAllCenterX metrics:nil views:views]; [self.contentView addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mainLabel]|" options: NSLayoutFormatAlignAllCenterX metrics:nil views:views]; [self.contentView addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel][mainLabel]|" options: NSLayoutFormatAlignAllLeft metrics:nil views:views]; [self.contentView addConstraints:constraints]; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:nameLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:44.0]]; [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:nameLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:1]]; } } 

对不起,大量的代码。 这是我的UITableView的tableView:cellForRowAtIndexPath:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0 || indexPath.row == 2 || indexPath.row == 3) { TVTCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIDTitle forIndexPath:indexPath]; [[cell nameLabel] setText:[nameArray objectAtIndex:indexPath.row]]; return cell; } else if (indexPath.row == 1 || indexPath.row == 4 || indexPath.row == 5) { TVTCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIDTitleMain forIndexPath:indexPath]; [[cell nameLabel] setText:[nameArray objectAtIndex:indexPath.row]]; [[cell mainLabel] setText:[dataArray objectAtIndex:indexPath.row]]; return cell; } else { UITableViewCell *badCell = [[UITableViewCell alloc] init]; NSLog(@"Warning! returning a cell that shouldnt be here"); badCell.textLabel.text = @"Warning!"; return badCell; } } 

最后,UITableView的viewDidLoad方法:

 - (void)viewDidLoad { [super viewDidLoad]; [[self tableView] registerClass:[TVTCell class] forCellReuseIdentifier:kCellIDTitle]; [[self tableView] registerClass:[TVTCell class] forCellReuseIdentifier:kCellIDTitleMain]; } 

你的代码有几个错误。 首先,我想你会发现,如果你做了一些日志logging,updateConstraints永远不会被调用。 我会把所有的代码放在init方法中。 另外,你的约束有几个错误。 将高度设置为44的约束不需要,因为您已经将标签固定到单元格的底部和底部。 我不知道你想用最后一个做什么,看起来这样会使名字标签1点宽。 此外,您不应将内容视图的translatesAutoresizingMaskIntoConstraints设置为NO,这会导致奇怪的效果。 所以这是我认为你想要的代码:

 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { reuseID = reuseIdentifier; nameLabel = [[UILabel alloc] init]; [nameLabel setTextColor:[UIColor blackColor]]; [nameLabel setBackgroundColor:[UIColor colorWithHue:32 saturation:100 brightness:63 alpha:1]]; [nameLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; [nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.contentView addSubview:nameLabel]; mainLabel = [[UILabel alloc] init]; [mainLabel setTextColor:[UIColor blackColor]]; [mainLabel setBackgroundColor:[UIColor colorWithHue:66 saturation:100 brightness:63 alpha:1]]; [mainLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; [mainLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.contentView addSubview:mainLabel]; NSDictionary *views = NSDictionaryOfVariableBindings(nameLabel, mainLabel); if (reuseID == kCellIDTitle) { NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" options: 0 metrics:nil views:views]; [self.contentView addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel]|" options: 0 metrics:nil views:views]; [self.contentView addConstraints:constraints]; } if (reuseID == kCellIDTitleMain) { NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" options:0 metrics:nil views:views]; [self.contentView addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mainLabel]|" options: 0 metrics:nil views:views]; [self.contentView addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel][mainLabel(==nameLabel)]|" options: 0 metrics:nil views:views]; [self.contentView addConstraints:constraints]; } } return self; } 

你可以使用下面的自动布局在swift 4中以编程方式创buildUITableViewCell。 这不完全是你在问题中指定的上述问题的解决scheme。更通用的实现如何使用自动布局以快速编程方式创buildTableview单元格:

 class ViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() tableView.register(CustomCell2.self, forCellReuseIdentifier: "cell") } override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 2 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? CustomCell2 else { return UITableViewCell() } cell.model = CellModel(labelString: "set constriant by code") return cell } } 

定义模型:

 struct CellModel { let labelString : String } 

定义自定义单元格:

 class CustomCell2 : UITableViewCell { private let label : UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false // enable auto layout label.backgroundColor = .green // to visualize the background of label label.textAlignment = .center // center text alignment return label }() private func addLabel() { addSubview(label) NSLayoutConstraint.activate([ // label width is 70% of cell width label.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.7), // label is horizontally center of cell label.centerXAnchor.constraint(equalTo: centerXAnchor) ]) } var model : CellModel? { didSet { label.text = model?.labelString ?? "" } } // Init override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) addLabel() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

这是以上程序的输出。

这是实际的项目,你可以看看。