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閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容