创建Xib文件
首先将Cell做好布局,调整到满意的位置和宽度,然后开始做Autolayout设定。
Autolayout操作方式有两种,一种是选择目标后,使用右下角的工具栏;另一种是直接使用右键拖拽目标,在弹出的菜单中选择限制项。当选择的目标比较小的时候,可以打开左侧的菜单,在这里做拖拽操作一样是可以的。个人感觉后者更方便一些。
开始之前,先来介绍下使用的基本工具吧。
第一个按钮是和对齐有关的,就是控制多个元素(Lable, Button等)的统一约束。例如我们需要让标题和内容按照左,就选择标题和内容元素,选择Leading Edges设置为5即可。
第二个按钮是和元素位置固定有关的限制条件,直接看图吧:
右侧能够看到当前选择元素限制条件的列表:
有时候想要一个元素的间距是一个动态值,例如距离右侧至少10pt(即>=10pt),那么可以在上图中点击右侧按钮(齿轮)进入详细设置:
第三个按钮是有关清除限制条件、根据限制更新视图大小的工具。个人比较常用的是清除限制条件,有时候设置错了很麻烦,直接清除掉重新来就行了。
上面这些就是常用到的一些限制条件了。个人觉得使用右键拖拽弹出的菜单选择更方便和直观一些,因为菜单中会根据拖拽内容动态显示可用项供我们选择,菜单如图
大致就是这些了吧……
我来谈谈自己的用法。总体上是从上到下,从左到右做约束限制。在这个例子中,就是设置标题->内容->发帖人这样的顺序。
设置标题的顶部和左侧距离,以及宽度(防止超出边界)。
设置内容的顶部(距离标题)和左侧距离,以及宽度。设置最大行数。
设置发帖人的顶部和左侧距离,以及高度。
设置发帖时间的顶部和左侧距离,距离右侧间距(防止内容过长)。
关键步骤,设置发帖人距离底部距离,如果不设置这个参数,那么下面代码计算的Cell高度会永远是0。
多试一试,如果有错误或者缺少限制,XCode会有提示。它报出的错误一般都是必须修正的,但它给的自动修正建议有时并不是我们想要的(正确的),想清楚再添加。
代码部分
使用了xib制作的Cell,那么在原来的项目代码中如何使用呢?看代码:
static NSString *CellIdentifier = @"CellIdentifier";
- (void)viewDidLoad
{
//注册TableView中用于复用的Cell
[self.tableView registerNib:[UINib nibWithNibName:@"BBSPostContentCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
//...
}
//关键方法,获取复用的Cell后模拟赋值,然后取得Cell高度
-
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
BBSPostContentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];NSDictionary *dataSourceItem = [self.dataSource objectAtIndex:indexPath.row];
cell.titleLabel.text = [dataSourceItem valueForKey:@"title"];
cell.contentLabel.text = [dataSourceItem valueForKey:@"body"];[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;
}
//在cellForRowAtIndexPath中,按照常规方法做赋值就行了
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BBSPostContentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];NSDictionary *dic = dataSource[indexPath.row];
cell.titleLabel.text = dic[@"title"];
cell.contentLabel.text = dic[@"body"];return cell;
}
我在使用Instruments分析发现,heightForRowAtIndexPath中调用dequeueReusableCellWithIdentifier会占用很多CPU资源,因此我试着不使用registerNib方法注册复用Cell,而在代码中手动处理,类似这样:
BBSPostContentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[NSBundle mainBundle] loadNibNamed:@"BBSPostContentCell" owner:self options:NULL][0];
NSLog(@"cell loadNibNamed");
} else {
NSLog(@"cell dequeueReusableCellWithIdentifier");
}
这时我发现这里的Cell调用dequeueReusableCellWithIdentifier方法总是返回nil,因此每次都是从xib中加载,从而耗费了大量的资源。问题的原因我还不清楚,目前我的解决方法是,单独生成一个Cell用于在heightForRowAtIndexPath方法中计算高度。
其次,在[tableView reloadData]和[tableView insertRowsAtIndexPaths]时,底层会将所有行高重新计算,这个会占用大量的时间,因此我试着对行高做了缓存,暂时解决了这个问题。