AutoLayout in UITableVIew及控件显示的优先级

现在IOS的屏幕尺寸也有很多,为了方便屏幕适配,autolayout能在我们在UI布局方面节省很多工作量,今天就讲一下在UITableView中如何使用AutoLayout,具体怎么实现我就不讲了,网上也有很多资料,我下面也会给出一个实现Demo,今天就一些细节方面,做一些知识的整理。

Demo gitHub:https://github.com/lerpo/UITableView-Autolayout/tree/master

为了方便讲解,我先把一些主要的代码贴出来:

#import <Foundation/Foundation.h>
@interface Person : NSObject

@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *summery;
@property(nonatomic,copy) NSString *imgUrl;
@property(nonatomic,copy) NSString *like;
@property(nonatomic,copy) NSString *date;
@property(nonatomic,copy) NSString *hot;

-(id)initWithName:(NSString *)name summary:(NSString *)summary imgUrl:(NSString *)imgUrl like:(NSString *)like hot:(NSString *)hot date:(NSString *)date;

@end
#import "Person.h"

@implementation Person

-(id)initWithName:(NSString *)name summary:(NSString *)summary imgUrl:(NSString *)imgUrl like:(NSString *)like hot:(NSString *)hot date:(NSString *)date{
    
    if(self = [super init])
    {
        _name = name;
        _summery = summary;
        _imgUrl = imgUrl;
        _like = like;
        _date = date;
        _hot = hot;
    }
    return self;
    
}
@end
知识
  • 定义一个构造函数方便,对象初始化赋值
#import <UIKit/UIKit.h>
@class Person;
@interface PersonTableCellTableViewCell : UITableViewCell

@property(nonatomic,strong) UILabel *name;
@property(nonatomic,strong) UILabel *summary;
@property(nonatomic,strong) UIImageView *headimg;
@property(nonatomic,strong) UIImageView *img;
@property(nonatomic,strong) UILabel *like;
@property(nonatomic,strong) UILabel *hot;
@property(nonatomic,strong) UILabel *date;
@property(nonatomic,strong) UIView *bottomView;
@property(nonatomic,assign) BOOL didSetupConstraints;

-(void)setData:(Person *)person;
@end
#import "PersonTableCellTableViewCell.h"
#import <Masonry.h>
#import "Person.h"
@implementation PersonTableCellTableViewCell

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if(self){
        self.name = [[UILabel alloc] init];
        self.name.numberOfLines = 1;
        self.name.textAlignment =  NSTextAlignmentLeft;
        self.name.textColor = [UIColor blackColor];
        
        self.summary = [[UILabel alloc] init];
        self.summary.numberOfLines = 0;
        [self.summary setLineBreakMode:NSLineBreakByTruncatingTail];
        self.summary.textAlignment =  NSTextAlignmentCenter;
        self.summary.textColor = [UIColor blackColor];
        
        self.headimg = [[UIImageView alloc] init];
        self.img = [[UIImageView alloc] init];
        
        self.bottomView = [[UIView alloc] init];
        
        self.like = [[UILabel alloc] init];
        self.like.textAlignment = NSTextAlignmentRight;
        
        self.hot = [[UILabel alloc] init];
        self.hot.textAlignment = NSTextAlignmentRight;
       
        self.date = [[UILabel alloc] init];
        self.date.textAlignment = NSTextAlignmentLeft;
        
        self.contentView.backgroundColor = [UIColor lightTextColor];
        [self.contentView addSubview:self.name];
        [self.contentView addSubview:self.summary];
        [self.contentView addSubview:self.headimg];
        [self.contentView addSubview:self.img];
        [self.bottomView addSubview:self.date];
        [self.bottomView addSubview:self.hot];
        [self.bottomView addSubview:self.like];
        [self.contentView addSubview:self.bottomView];
        
    }
    return self;
}
-(void)updateConstraints
{
    if(!self.didSetupConstraints)
    {
    [self.headimg mas_makeConstraints:^(MASConstraintMaker *make) {
      make.left.equalTo(self.contentView.mas_left).with.offset(10);
      make.top.equalTo(self.contentView.mas_top).with.offset(10);
      make.width.mas_lessThanOrEqualTo(@50);
      make.height.mas_lessThanOrEqualTo(@50);
    }];
    
    [self.name mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.headimg.mas_right).with.offset(10);
        make.top.equalTo(self.contentView.mas_top).with.offset(5);
        make.height.equalTo(@40);
        make.right.equalTo(self.contentView.mas_right).with.offset(-5);
    }];
    
    
    [self.summary mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.contentView.mas_left).with.offset(10);
        make.top.equalTo(self.headimg.mas_bottom).with.offset(5);
        make.right.equalTo(self.contentView.mas_right).with.offset(-10);
        make.bottom.equalTo(self.img.mas_top).with.offset(0);

    }];
    [self.img mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.contentView.mas_left).with.offset(10);
        make.top.equalTo(self.summary.mas_bottom).with.offset(0);
        make.right.equalTo(self.contentView.mas_right).with.offset(-10);
        make.height.mas_lessThanOrEqualTo(@200);
        make.bottom.equalTo(self.bottomView.mas_top).with.offset(10);
        
    }];
    [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.contentView.mas_left).with.offset(10);
        make.right.equalTo(self.contentView.mas_right).with.offset(-10);
        make.bottom.equalTo(self.contentView.mas_bottom).with.offset(-5);
    }];
        
     [self.date mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.equalTo(self.bottomView.mas_left).with.offset(10);
         make.top.equalTo(self.bottomView.mas_top).with.offset(5);
         make.bottom.equalTo(self.bottomView.mas_bottom).with.offset(-5);
         make.right.equalTo(self.hot.mas_left).with.offset(-5);
        
     }];
        [self.date setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
        

        self.date.backgroundColor = [UIColor blueColor];
     [self.hot mas_makeConstraints:^(MASConstraintMaker *make) {
         
         make.top.equalTo(self.bottomView.mas_top).with.offset(5);
         make.right.equalTo(self.like.mas_left).with.offset(-5);
         make.bottom.equalTo(self.bottomView.mas_bottom).with.offset(-5);
     }];
        [self.hot setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
        self.hot.backgroundColor = [UIColor yellowColor];
     [self.like mas_makeConstraints:^(MASConstraintMaker *make) {
         make.top.equalTo(self.bottomView.mas_top).with.offset(5);
         make.right.equalTo(self.bottomView.mas_right).with.offset(-5);
         make.bottom.equalTo(self.bottomView.mas_bottom).with.offset(-5);
     }];
        self.like.backgroundColor = [UIColor redColor];
        [self.like setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
       
        
    }
     self.didSetupConstraints = YES;
    [super updateConstraints];
}

-(void)layoutSubviews{

    [super layoutSubviews];
    [self.contentView setNeedsLayout];
    [self.contentView layoutIfNeeded];
    self.summary.preferredMaxLayoutWidth = CGRectGetWidth(self.summary.frame);
    
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

-(void)setData:(Person *)person{
    self.name.text = person.name;
    self.headimg.image = [UIImage imageNamed:@"bee_00_coughing"];
    self.summary.text = person.summery;
    self.img.image = [UIImage imageNamed:person.imgUrl];
    self.date.text = person.date;
    self.like.text = person.like;
    self.hot.text = person.hot;
    
    NSLog(@"date****%lf",self.date.intrinsicContentSize.width);
    NSLog(@"like****%lf",self.like.intrinsicContentSize.width);
    NSLog(@"hot****%lf",self.hot.intrinsicContentSize.width);
}

@end
知识
  • self.summary.numberOfLines = 0;

UILabel自动换行,在不同的iOS版本下表现不一致导致的UI问题
表现为在iOS7以上的系统中,UILabel能够自动换行,多行显示的字符串,而在iOS6上面则不会自动换行,直接打省略号。
正常情况下,numberOfLines设置为0,UILabel就会自动换行了。
但是在iOS6下面需要设置preferredMaxLayoutWidth,autolayout才会判断到折行的位置,才能正确的显示多行的UILabel
但是 preferredMaxLayoutWidth设置为多少才是正确的呢?
如果你知道一个确切的width当然是最好的,那么直接设置即可,
但是如果UILabel的宽度是自适应的,不确定,那么可以使用如下的代码设置

self.summary.preferredMaxLayoutWidth = CGRectGetWidth(self.summary.frame);
  • if(!self.didSetupConstraints)

如果你用代码来设置布局约束,你应该在UITableViewCell子类的updateConstraints方法里面一次性完成。注意,updateConstraints可能不止被调用一次,因此要避免重复添加相同的布局约束。在updateConstraints中,可以将添加布局约束的代码包在一个if条件语句中(比如用一个叫didSetupConstraints的布尔属性,运行一次添加布局约束的代码后就将其设置为YES),以确保不重复添加相同的布局约束。另外,更新已有布局约束的代码(比如调整布局约束的constant属性),也应该将它们放置在updateConstraints 中,但是要在didSetupConstraints条件语句的外面,这样才可以确保每次调用的时候都会被执行。

  • [self.contentView setNeedsLayout];

UIView的setNeedsDisplay和setNeedsLayout方法
-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
两个方法都是异步执行的。而setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到 UIGraphicsGetCurrentContext,就可以画画了。而setNeedsLayout会默认调用layoutSubViews,
就可以 处理子视图中的一些数据。
综上所诉,setNeedsDisplay方便绘图,而layoutSubViews方便出来数据。
layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews。
2、addSubview会触发layoutSubviews。
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
4、滚动一个UIScrollView会触发layoutSubviews。
5、旋转Screen会触发父UIView上的layoutSubviews事件。
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
7、直接调用setLayoutSubviews。

drawRect在以下情况下会被调用:
1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect调用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量值).
2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
以上1,2推荐;而3,4不提倡

drawRect方法使用注意点:
1、若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或者 setNeedsDisplayInRect,让系统自动调该方法。
2、若使用calayer绘图,只能在drawInContext: 中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕

  • [self.likesetContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];

Content Hugging Priority代表控件拒绝拉伸的优先级。优先级越高,控件会越不容易被拉伸。

Content Compression Resistance Priority代表控件拒绝压缩内置空间的优先级。优先级越高,控件的内置空间会越不容易被压缩。而这里的内置空间,就是上面讲的UIView的intrinsicContentSize。
可以直接通过UIView的setContentHuggingPriority:forAxis方法来设置控件的Content Hugging Priority,其中forAxis参数代表横向和纵向,本例中只需要设置纵向,所以传入UILayoutConstraintAxisVertical.
Priority 有以下几种类型:

static const UILayoutPriority UILayoutPriorityRequired NS_AVAILABLE_IOS(6_0) = 1000; // A required constraint.  Do not exceed this.
static const UILayoutPriority UILayoutPriorityDefaultHigh NS_AVAILABLE_IOS(6_0) = 750; // This is the priority level with which a button resists compressing its content.
static const UILayoutPriority UILayoutPriorityDefaultLow NS_AVAILABLE_IOS(6_0) = 250; // This is the priority level at which a button hugs its contents horizontally.
static const UILayoutPriority UILayoutPriorityFittingSizeLevel NS_AVAILABLE_IOS(6_0) = 50; // When you send -[UIView systemLayoutSizeFittingSize:], the size fitting most closely to the target size (the argument) is computed.  UILayoutPriorityFittingSizeLevel is the priority level with which the view wants to conform to the target size in that computation.  It's quite low.  It is generally not appropriate to make a constraint at exactly this priority.  You want to be higher or lower.

本例是:

     [self.date mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.equalTo(self.bottomView.mas_left).with.offset(10);
         make.top.equalTo(self.bottomView.mas_top).with.offset(5);
         make.bottom.equalTo(self.bottomView.mas_bottom).with.offset(-5);
         make.right.equalTo(self.hot.mas_left).with.offset(-5);
        
     }];
        [self.date setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
        

        self.date.backgroundColor = [UIColor blueColor];
     [self.hot mas_makeConstraints:^(MASConstraintMaker *make) {
         
         make.top.equalTo(self.bottomView.mas_top).with.offset(5);
         make.right.equalTo(self.like.mas_left).with.offset(-5);
         make.bottom.equalTo(self.bottomView.mas_bottom).with.offset(-5);
     }];
        [self.hot setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
        self.hot.backgroundColor = [UIColor yellowColor];
     [self.like mas_makeConstraints:^(MASConstraintMaker *make) {
         make.top.equalTo(self.bottomView.mas_top).with.offset(5);
         make.right.equalTo(self.bottomView.mas_right).with.offset(-5);
         make.bottom.equalTo(self.bottomView.mas_bottom).with.offset(-5);
     }];
        self.like.backgroundColor = [UIColor redColor];
        [self.like setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];

及date的优先级最低,也就是说它最先会被压缩,hot其次 like最高,也就是说当一行文本显示这三个控件时,当文本放不下时,首先会压缩date里面的内容,如果其他两项的内容太长,以至于date一点都显示不了,那么就会压缩hot里面的文本内容。最后才是like.

#import "ViewController.h"
#import "Person.h"
#import "PersonTableCellTableViewCell.h"
static NSString *CellIdentifier = @"CellIdentifier";
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>

@property(nonatomic ,strong) UITableView *tableView;

@property(nonatomic ,copy) NSMutableArray *dataSource;

@property (strong, nonatomic) NSMutableDictionary *offscreenCells;

@end

@implementation ViewController

-(UITableView *)tableView
{
  if(_tableView == nil)
  {
      _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
      _tableView.estimatedRowHeight = UITableViewAutomaticDimension;
      _tableView.estimatedRowHeight = 44.0;
      _tableView.delegate = self;
      _tableView.dataSource = self;
      
  }
    return _tableView;
}

-(NSMutableDictionary *)offscreenCells{
    if(_offscreenCells==nil){
        _offscreenCells = [NSMutableDictionary dictionary];
    }
    return _offscreenCells;
}

-(NSMutableArray *)dataSource{
    
    if(_dataSource == nil){
        
        _dataSource = [[NSMutableArray alloc] initWithCapacity:10];
       
    }
    return _dataSource;
    
}

-(void)dataSorces{
    Person *person = [[Person alloc] initWithName:@"天ttan"
                                          summary:@"我是7个月大的宝宝,我喜欢听音乐看电视"
                                           imgUrl:@"bee_16_lunch"
                                           like:@"点赞:100000000000"
                                           hot:@"人气:100"
                                           date:@"2015-06-09 2015-06-09 2015-06-09"
                      ];
    [self.dataSource addObject:person];
    
    Person *person1 = [[Person alloc] initWithName:@"天ttan"
                                          summary:@"我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视我是7个月大的宝宝,我喜欢听音乐看电视"
                                              imgUrl:@"bee_16_lunch"
                                              like:@"点赞:100"
                                               hot:@"人气:100000000000"
                                              date:@"2015-06-09"];
    [self.dataSource addObject:person1];

    
    Person *person2 = [[Person alloc] initWithName:@"天ttan"
                                          summary:@"我是7个月大的宝宝,我喜欢听音乐看电视"
                                           imgUrl:@""
                                              like:@"点赞:2300000000000000000"
                                               hot:@"人气:100000000000000000"
                                              date:@"2015-06-09"];
    [self.dataSource addObject:person2];

    
    Person *person3 = [[Person alloc] initWithName:@"天ttan"
                                          summary:@""
                                           imgUrl:@"bee_16_lunch"
                                              like:@"点赞:10"
                                               hot:@"人气:10"
                                              date:@"2015-06-09"];
    [self.dataSource addObject:person3];
    [self.dataSource addObject:person];
    [self.dataSource addObject:person1];
    [self.dataSource addObject:person2];
    [self.dataSource addObject:person3];
   
}
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.tableView];
     [self dataSorces];
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.dataSource.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    PersonTableCellTableViewCell *cell  = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil){
        cell = [[PersonTableCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    Person *person = self.dataSource[indexPath.row];
    [cell setData:person];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
//  [cell setNeedsUpdateConstraints]; //
    [cell updateConstraintsIfNeeded];//立即触发约束更新,自动更新布局。

    return cell;
    
    
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    PersonTableCellTableViewCell *cell  = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil){
        cell = [[PersonTableCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    Person *person = self.dataSource[indexPath.row];
    [cell setData:person];
    
//  [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
    
    cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
//  [cell setNeedsLayout]; //而setNeedsLayout会默认调用layoutSubViews
    [cell layoutIfNeeded];
    
    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    height += 1;
    return height;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
知识
  • _tableView.estimatedRowHeight = UITableViewAutomaticDimension; _tableView.estimatedRowHeight = 44.0;
    在iOS8上,苹果将许多在iOS8之前比较难实现的东西都内置实现了。为了让cell实现self-sizing的机制,必须先将tableView的rowHeight
    属性设置为常量UITableViewAutomaticDimension
    。然后,只需将tableView的estimatedRowHeight
    属性设置为非零值即可开启行高估算功能,
    这样做就为tableView上还没有显示在屏幕上的cell提供了一个临时的估算的行高。然后,当cell即将滚入屏幕范围内的时候,会计算出实际的高度。为了确定每一行的实际高度,tableView会自动让每个cell基于其contentView的已知固定宽度(tableView的宽度,减去其他额外的,像section index或accessoryView这些宽度)和被加到contentView及其子视图上的自动布局约束规则来计算contentView
    的高度。一旦真正的行高被计算出来后,旧的估算的行高会被更新为这个真实的行高(并且其他任何需要对tableView的contentSize或contentOffset的更改都自动替你完成了)。
    一般来说,行高估算值不需要太精确——它只是被用来修正tableView中滚动条的大小的,当你在屏幕上滑动cell的时候,即便估算值不准确,tableView还是能很好地调节滚动条。将tableView的estimatedRowHeight
    属性设置成(在viewDidLoad
    或类似的方法中)一个接近于“平均”行高的常量值即可。*只有行高变化很极端的时候(比如相差一个数量级),才会在滚动时产生滚动条“跳跃”的现象。这个时候,你才应当实现tableView:estimatedHeightForRowAtIndexPath:
    方法,为每一行返回一个更精确的估算值。
    iOS7支持(需要自己实现cell尺寸自适应功能)
  1. 完成一个完整的布局过程 & 计算cell的高度
    首先,为每一个cell都初始化一个离屏(offscreen)实例,为每个重用标示符实例化一个与之对应的cell实例,这些cell完全用于高度计算。(离屏表示cell的引用被存储在view controller的一个属性或实例变量之中,并且这个cell绝对不会被用作tableView:cellForRowAtIndexPath:方法的返回值以实际呈现在屏幕上。)接着,这个cell的内容(例如,文本、图片等等)还必须和会被显示在table view中的内容完全一致。
    然后,强制cell立即更新子视图的布局,再用cell的contentView调用systemLayoutSizeFittingSize:方法计算出cell所需的高度是多少。使用UILayoutFittingCompressedSize参数可以得到适合cell中所有内容所需的最小尺寸。然后其高度就可以作为tableView:heightForRowAtIndexPath:方法的返回值。
  • height += 1.0f;

要为cell的分割线加上额外的1pt高度。因为分隔线是被加在cell底边和contentView底边之间的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容