等高的Cell緩存
1、storyboard方式佈局
建立一個繼承自UITableViewCell的子類字體
在storyboard中atom
- 往cell裏面增長鬚要用到的子控件spa
- 設置cell的重用標識code
- 設置cell的class爲我剛纔建立的那個Cell類型XXDealCellorm
3. 在控制器中繼承
- 利用重用標識找到cellstring
- 給cell傳遞模型數據it
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.deals.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"deal"; XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //取出模型數據 cell.deal = self.deals[indexPath.row]; return cell; }
4.在XXDealCell中,將storyboard中的子控件連線到類擴展中,而且提供一個模型屬性,重寫模型的set方法,在這個方法中設置模型數據到子控件上。
// // XXDealCell.m // 自定義等高的cell // // Created by Daniel on 16/3/17. // Copyright © 2016年 Daniel. All rights reserved. // #import "XXDealCell.h" #import "XXDeal.h" @interface XXDealCell() @property (weak, nonatomic) IBOutlet UIImageView *iconView; @property (weak, nonatomic) IBOutlet UILabel *titleLable; @property (weak, nonatomic) IBOutlet UILabel *priceLable; @property (weak, nonatomic) IBOutlet UILabel *buyCountLable; @end @implementation XXDealCell - (void)setDeal:(XXDeal *)deal { _deal = deal; //設置數據 self.iconView.image = [UIImage imageNamed:deal.icon]; self.titleLable.text = deal.title; self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price]; self.buyCountLable.text = [NSString stringWithFormat:@"%@人已購買", deal.buyCount]; } @end
2、xib方式
1.建立一個繼承自UITableViewCell的子類,好比XXDealCell
2.建立一個xib文件(文件名建議跟cell的類名同樣),好比XXDealCell.xib,拖拽一個UITableViewCell出來,修改cell的class爲XXDealCell,設置cell的重用標識,往cell中添加須要用到的子控件
這兩步和storyboard方式都是大同小異。
3.在控制器中,利用registerNib...方法註冊xib文件,利用重用標識找到cell(若是沒有註冊xib文件,就須要手動去加載xib文件),給cell傳遞模型數據。
- (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XXDealCell class]) bundle:nil] forCellReuseIdentifier:@"deal"]; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"deal"; XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //若是不註冊,就要這樣手動加載xib // if(cell == nil) { // cell = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([XXDealCell class]) owner:nil options:nil]lastObject]; // } //取出模型數據 cell.deal = self.deals[indexPath.row]; return cell; }
4.在XXDealCell中,將xib中的子控件連線到類擴展中,須要提供一個模型屬性,重寫模型的set方法,在這個方法中設置模型數據到子控件上,也能夠將建立得到cell的代碼封裝起來(好比cellWithTableView:方法)
// // XXDealCell.m // 自定義等高的cell // // Created by Daniel on 16/3/17. // Copyright © 2016年 Daniel. All rights reserved. // #import "XXDealCell.h" #import "XXDeal.h" @interface XXDealCell() @property (weak, nonatomic) IBOutlet UIImageView *iconView; @property (weak, nonatomic) IBOutlet UILabel *titleLable; @property (weak, nonatomic) IBOutlet UILabel *priceLable; @property (weak, nonatomic) IBOutlet UILabel *buyCountLable; @end @implementation XXDealCell - (void)setDeal:(XXDeal *)deal { _deal = deal; //設置數據 self.iconView.image = [UIImage imageNamed:deal.icon]; self.titleLable.text = deal.title; self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price]; self.buyCountLable.text = [NSString stringWithFormat:@"%@人已購買", deal.buyCount]; } + (instancetype)cellWithTableView:(UITableView *) tableView { static NSString *ID = @"deal"; XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if(cell == nil) { cell = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([XXDealCell class]) owner:nil options:nil]lastObject]; } return cell; } @end
- (void)viewDidLoad { [super viewDidLoad]; // [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XXDealCell class]) bundle:nil] forCellReuseIdentifier:@"deal"]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.deals.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XXDealCell *cell = [XXDealCell cellWithTableView:tableView]; //取出模型數據 cell.deal = self.deals[indexPath.row]; return cell; }
3、代碼方式
-------------使用frame
1.建立一個繼承自UITableViewCell的子類,好比XXDealCell
- 在initWithStyle:reuseIdentifier:方法中添加子控件,設置子控件的初始化屬性(好比文字顏色、字體)等
- 在layoutSubviews方法中設置子控件的frame
- 須要提供一個模型屬性,重寫模型的setter方法,在這個方法中設置模型數據到子控件
//一、在initWithStyle:reuseIdentifier:方法中添加子控件 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if(self == [super initWithStyle:style reuseIdentifier:reuseIdentifier ]) { UIImageView *iconView = [[UIImageView alloc]init]; [self.contentView addSubview:iconView]; self.iconView = iconView; UILabel *titleLable = [[UILabel alloc]init]; [self.contentView addSubview:titleLable]; self.titleLable = titleLable; UILabel *priceLable = [[UILabel alloc]init]; [self.contentView addSubview:priceLable]; priceLable.textColor = [UIColor orangeColor]; self.priceLable = priceLable; UILabel *buyCountLable = [[UILabel alloc]init]; [self.contentView addSubview:buyCountLable]; buyCountLable.textAlignment = NSTextAlignmentRight; buyCountLable.font = [UIFont systemFontOfSize:11]; buyCountLable.textColor = [UIColor lightGrayColor]; self.buyCountLable = buyCountLable; } return self; } //二、在layoutSubviews方法中設置子控件的frame - (void)layoutSubviews { [super layoutSubviews]; //iconView CGFloat iconX = 10; CGFloat iconY = 10; CGFloat iconW = 100; CGFloat iconH = self.contentView.frame.size.height - 2 * iconY; self.iconView.frame = CGRectMake(iconX, iconY, iconW, iconH); //titleLable CGFloat titleX = CGRectGetMaxX(self.iconView.frame) + 10; CGFloat titleY = iconY; CGFloat titleW = self.contentView.frame.size.width - titleX - 10; CGFloat titleH = 20; self.titleLable.frame = CGRectMake(titleX, titleY, titleW, titleH); //priceView CGFloat priceX = titleX; CGFloat priceH = 20; CGFloat priceY = self.contentView.frame.size.height - priceH - 10; CGFloat priceW = 70; self.priceLable.frame = CGRectMake(priceX, priceY, priceW, priceH); //buyCountView CGFloat buyH = priceH; CGFloat buyY = self.contentView.frame.size.height - 10 - buyH; CGFloat buyX = priceX + priceW + 10; CGFloat buyW = self.contentView.frame.size.width - buyX - 10; self.buyCountLable.frame = CGRectMake(buyX, buyY, buyW, buyH); } //三、重寫模型的setter方法 - (void)setDeal:(XXDeal *)deal { _deal = deal; //設置數據 self.iconView.image = [UIImage imageNamed:deal.icon]; self.titleLable.text = deal.title; self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price]; self.buyCountLable.text = [NSString stringWithFormat:@"%@人已購買", deal.buyCount]; }
2.在控制器中,利用registerClass...方法註冊XMGDealCell類,利用重用標識找到cell(若是沒有註冊類,就須要手動建立cell,給cell傳遞模型數據,也能夠將建立得到cell的代碼封裝起來(好比cellWithTableView:方法)。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XXDealCell *cell = [XXDealCell cellWithTableView:tableView]; //取出模型數據 cell.deal = self.deals[indexPath.row]; return cell; }
---------------------使用autoLayout
與使用frame不一樣的是:在initWithStyle:reuseIdentifier:方法中添加子控件後直接添加約束,而後不須要layoutSubviews方法了。其餘都是同樣的,添加約束使用Masonry。
//一、在initWithStyle:reuseIdentifier:方法中添加子控件 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if(self == [super initWithStyle:style reuseIdentifier:reuseIdentifier ]) { CGFloat margin = 10; UIImageView *iconView = [[UIImageView alloc]init]; [self.contentView addSubview:iconView]; self.iconView = iconView; [iconView makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(100); make.left.top.equalTo(self.contentView).offset(margin); make.bottom.equalTo(self.contentView).offset(-margin); }]; UILabel *titleLable = [[UILabel alloc]init]; [self.contentView addSubview:titleLable]; self.titleLable = titleLable; [titleLable makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(iconView.right).offset(margin); make.top.equalTo(iconView); make.right.equalTo(self.contentView).offset(-margin); }]; UILabel *priceLable = [[UILabel alloc]init]; [self.contentView addSubview:priceLable]; priceLable.textColor = [UIColor orangeColor]; self.priceLable = priceLable; [priceLable makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(titleLable); make.bottom.equalTo(iconView); }]; UILabel *buyCountLable = [[UILabel alloc]init]; [self.contentView addSubview:buyCountLable]; buyCountLable.textAlignment = NSTextAlignmentRight; buyCountLable.font = [UIFont systemFontOfSize:11]; buyCountLable.textColor = [UIColor lightGrayColor]; self.buyCountLable = buyCountLable; [buyCountLable makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(priceLable); make.right.equalTo(self.contentView).offset(-margin); make.left.equalTo(priceLable).offset(margin); }]; } return self; }
非等高cell
xib自定義非等高cell
- 在模型中增長一個cellHeight屬性,用來存放對應cell的高度
/** * cell的高度 */ @property(assign, nonatomic)CGFloat cellHeight;
- 在cell的模型屬性setter方法中調用[self layoutIfNeed]方法強制佈局,而後計算出模型的cellheight屬性值
//強制佈局 [self layoutIfNeeded];
- 在控制器中實現tableView:estimatedHeightForRowAtIndexPath:方法,返回一個估計高度
/** * 返回每個cell的估計高度 * * @param tableView * @param indexPath * * @return 只要返回了估計高度,tableView就會先調用tableView:cellForRowAtIndexPath:方法建立cell * 再調用tableView:heightForRowAtIndexPath:方法獲取cell的真實高度 */ - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { return 100; }
- 在控制器中實現tableView:heightForRowAtIndexPath:方法,返回cell的真實高度(模型中的cellHeight屬性)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XXStatusCell *cell = [XXStatusCell cellWithTableView:tableView]; //設置數據 cell.status = self.statuses[indexPath.row]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { XXStatus *status = self.statuses[indexPath.row]; return status.cellHeight; }
二、storyboard方式自定義非等高cell
用storyboard和xib其實大同小異,直接在storyboard中添加子控件並添加約束,設置重用標識,修改cell的類,修改cell爲動態建立類型。注意,若是Lable要顯示多行的話,Lines要改成0,並且cell高度極端準確,要加一個方法:
- (void)awakeFromNib { self.contentLable.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20; }
而後獲取cell時直接在緩存池中根據重用標識去查找,其餘的和xib方式同樣。
+ (instancetype)cellWithTableView :(UITableView *)tableView { return [tableView dequeueReusableCellWithIdentifier:@"status"]; }