iOS UITableView5種行高自適應方案的選擇

下面將給出了5種Cell自適應高度的方案,并對比每種實現(xiàn)方案的流暢度吊档。從UI最不流暢的一種開始判沟,我們慢慢優(yōu)化。通過觀察屏幕的FPS來判斷屏幕在操作時是否卡頓恶导。關于對FPS的實時監(jiān)測浆竭,使用了YYKit-Demo中FPS控件來實現(xiàn)。點擊列表中不同Cell都會跳轉(zhuǎn)相同的內(nèi)容列表頁惨寿。只不過每個Cell所對應的內(nèi)容頁面的Cell自適應高度的實現(xiàn)方式不同邦泄。


5種Cell高度自適應方案

1.Autolayout + AutomaticDimension

點擊第一個Cell進入的頁面完全由AutoLayout進行布局,Cell自適應的高度也不用我們自己計算裂垦,而是使用系統(tǒng)提供的解決方案UITableViewAutomaticDimension來解決顺囊。當然,使用UITableViewAutomaticDimension要依賴于你添加的約束蕉拢,稍后會介紹到特碳。這種實現(xiàn)方案用起來簡單,不過UI流暢度方面不太理想晕换。當TableView快速滑動時午乓,就會出現(xiàn)嚴重的掉幀。親測FPS最低值38届巩!


545446-20160922151158059-1130164887.gif
#//第1步:設置預估值
self.tableView.estimatedRowHeight = 100.0;  

#//第2步:返回UITableViewAutomaticDimension 自動調(diào)整約束硅瞧,性能非常低
-  (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return UITableViewAutomaticDimension;      
}
cell所有子控件和底部動態(tài)label的約束
動態(tài)label關鍵的約束,撐開cell

2.Autolayout + CountHeight

依然是采用AutoLayout的方式來對Cell的內(nèi)容進行布局,不過Cell的高度我們是自己計算的恕汇,計算的過程是放在子線程中進行的腕唧,所以這種實現(xiàn)方式要優(yōu)于第一種實現(xiàn)方式,親測FPS最低值36瘾英!


手動計算行高枣接,Autolayout布局
- (void)createDataSupport {

    self.dataSupport = [[DataSupport alloc] init];
    __weak typeof (self) weak_self = self;
    [self.dataSupport setUpdataDataSourceBlock:^(NSMutableArray *dataSource) {
        weak_self.dataSource = dataSource;
        [weak_self.tableView reloadData];
    }];

    [self addTestData];
}

- (void)addTestData {

    dispatch_queue_t concurrentQueue = dispatch_queue_create("zeluli.concurrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_semaphore_t lock = dispatch_semaphore_create(1);
    
    for (int i = 0; i < 50; i ++) {
        dispatch_group_async(group, concurrentQueue, ^{
            dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
            [self createTestModel];
            dispatch_semaphore_signal(lock);
        });
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        [self updateDataSource];
    });
}

- (void)createTestModel {
    TestDataModel * model = [[TestDataModel alloc] init];
    model.title = @"行歌";
    
    NSDateFormatter *dataFormatter = [[NSDateFormatter alloc] init];
    [dataFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    model.time = [dataFormatter stringFromDate:[NSDate date]];
    
    NSString *imageName = [NSString stringWithFormat:@"%d.jpg", arc4random() % 6];
    model.imageName =imageName;
    
    NSInteger endIndex = arc4random() % contentText.length;
    model.content = [contentText substringToIndex:endIndex];
    
    model.textHeight = [self countTextHeight:model.content];
    model.cellHeight = model.textHeight + 60;
    
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:model.content];
    text.font = [UIFont systemFontOfSize:14];
    text.lineSpacing = 3;
    model.attributeContent = text;
    
    model.attributeTitle = [[NSAttributedString alloc] initWithString:model.title];
    model.attributeTime = [[NSAttributedString alloc] initWithString:model.time];
    
    [self.dataSource addObject:model];
}

-(CGFloat)countTextHeight:(NSString *) text {

    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    style.lineSpacing = 0;
    UIFont *font = [UIFont systemFontOfSize:14];
    [attributeString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, text.length)];
    [attributeString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, text.length)];
    NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
    CGRect rect = [attributeString boundingRectWithSize:CGSizeMake(SCREEN_WIDTH - 30, CGFLOAT_MAX) options:options context:nil];

    return rect.size.height + 40;
}

- (void)updateDataSource {

    if (self.updateDataBlock != nil) {
        self.updateDataBlock(self.dataSource);
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    if (indexPath.row < self.dataSource.count) {
        TestDataModel *model = self.dataSource[indexPath.row];
        return model.cellHeight;
    }

    return 100;
}

@implementation AutolayoutTableViewCell

- (void)configCellData:(TestDataModel *)model {//配置cell中的數(shù)據(jù)
    
    [self.headerImageView setImage:[[ImageCache shareInstance] getCacheImage:model.imageName]];
    [self.titleLable setText:model.title];
    [self.timeLabel setText:model.time];
    [self.contentLabel setText:model.content];
}

3.FrameLayout + CountHeight

為了進一步提高流暢度,我們采用了純Frame布局缺谴,因為Autolayout最終還是會被轉(zhuǎn)換成Frame進行布局的但惶,所以我們就用Frame對整個Cell中的所有子控件進行布局。當然Cell高度及可變內(nèi)容的高度,跟第2種方法一樣都是在子線程中進行計算的膀曾,這優(yōu)化的重要一步县爬。這種實現(xiàn)方式還是比較流暢的,可以作為折中的方案.親測FPS最低值42添谊!


手動計算行高财喳,frame布局

4.YYKit + CountHeight

545446-20160922151158059-1130164887.gif

接下來我們繼續(xù)進行優(yōu)化,引入第三方UI組件YYKit斩狱。將Cell上的組件替換成YYKit所提供的組件耳高。然后使用Frame進行布局,當然也是在子線程中對Cell的高度進行了計算所踊。效果還是比較流暢的泌枪,但是還未達到完全不掉幀的效果。親測FPS最低值53秕岛!

@property (strong, nonatomic) UIImageView *headerImageView;
@property (strong, nonatomic) YYLabel *titleLable;
@property (strong, nonatomic) YYLabel *timeLabel;
@property (strong, nonatomic) YYTextView *contentTextView;

5.AsyncDisplayKit + CountHeight

我們用Facebook提供的第三方庫來進行基礎組件的替換碌燕,將我們使用到的組件替換成AsyncDisplayKit相應的Note。這些Note是對系統(tǒng)組件的重組瓣蛀,對組件的顯示進行了優(yōu)化陆蟆,讓其渲染更為流暢,親測FPS最低值59惋增!
如果你對UI流暢度要求比較高的話叠殷,那么AsyncDisplayKit是一個比較好的選擇。不過會嚴重依賴AsyncDisplayKit诈皿,如果AsyncDisplayKit停止維護了林束,后期對AsyncDisplayKit進行替換的話,工作量還是比較大的稽亏。因為這種布局框架不像網(wǎng)絡框架壶冒,我們可以對網(wǎng)絡框架的調(diào)用進行提取,網(wǎng)絡層統(tǒng)一對外接口截歉,很方便切換到其他網(wǎng)絡請求庫胖腾。但是像AsyncDisplayKit這種框架會散布于UI層的各個角落,封裝提取不易瘪松,更不用說輕而易舉的替換了咸作。所以像這種頁面的實現(xiàn),個人還是偏向于Framelayout + CountHeight的方式來實現(xiàn)宵睦。

@property (strong, nonatomic) ASImageNode *headerImageNode;
@property (strong, nonatomic) ASTextNode *titleTextNode;
@property (strong, nonatomic) ASTextNode *timeTextNode;
@property (strong, nonatomic) ASTextNode *contentTextNode;

總結:

  • 1记罚、2方案對比,手動計算行高優(yōu)于自適應行高
  • 2壳嚎、3方案對比桐智,frame優(yōu)于Autolayout
  • 3末早、4、5方案说庭, 根據(jù)實際情況進行選擇然磷,方案5最優(yōu),缺點同樣明顯刊驴,侵入性強

參考資料:https://www.cnblogs.com/ludashi/p/5895725.html
參考資料:https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末样屠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缺脉,更是在濱河造成了極大的恐慌,老刑警劉巖悦穿,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攻礼,死亡現(xiàn)場離奇詭異,居然都是意外死亡栗柒,警方通過查閱死者的電腦和手機礁扮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞬沦,“玉大人太伊,你說我怎么就攤上這事」渥辏” “怎么了僚焦?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長曙痘。 經(jīng)常有香客問我芳悲,道長,這世上最難降的妖魔是什么边坤? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任名扛,我火速辦了婚禮,結果婚禮上茧痒,老公的妹妹穿的比我還像新娘肮韧。我一直安慰自己,他們只是感情好旺订,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布弄企。 她就那樣靜靜地躺著,像睡著了一般耸峭。 火紅的嫁衣襯著肌膚如雪桩蓉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天劳闹,我揣著相機與錄音院究,去河邊找鬼洽瞬。 笑死,一個胖子當著我的面吹牛业汰,可吹牛的內(nèi)容都是我干的伙窃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼样漆,長吁一口氣:“原來是場噩夢啊……” “哼为障!你這毒婦竟也來了?” 一聲冷哼從身側響起放祟,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鳍怨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后跪妥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鞋喇,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年眉撵,在試婚紗的時候發(fā)現(xiàn)自己被綠了侦香。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡纽疟,死狀恐怖罐韩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情污朽,我是刑警寧澤散吵,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蟆肆,受9級特大地震影響错蝴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜颓芭,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一顷锰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亡问,春花似錦官紫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至床玻,卻和暖如春毁涉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锈死。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工贫堰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留穆壕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓其屏,卻偏偏與公主長得像喇勋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子偎行,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容