UIColletionView性能调研结果

UIColletionView性能调研结果

在之前的code review会议中,遗留了两个问题:

一、

  1. 复用cell,cell中嵌套子view

  2. 全部使用复用cell

    哪种性能更好?

  1. cell中的子View,使用addSubView和removeFormSuperView来控制子View显示与隐藏

  2. cell中的子View,一次性addSubView,然后使用hidden属性,来控制子view显示与隐藏

    哪种性能更好?

上述是使用文字表述可能理解起来略加困难,我们具体可以参考以下代码。并附上相应代码的视频,可以直观的看出性能的变化情况

一、

  1. 复用cell,cell中嵌套子view

    每个UICollectoinViewCell中包含10个子view。

    UICollectoinView 总共返回5000个cell。每个cell的长宽为屏幕的1/3。总共15000个view

    代码表述如下:

​
@implementation ReuseAllView
- (instancetype)initWithFrame:(CGRect)frame {
 if (self = [super initWithFrame:frame]) {
 [self setUpView];
 }
 return self;
}
​
- (void)setUpView {
 NSInteger i = 0;
 CGFloat margin = 10;
 NSInteger count_row = 10;
 CGFloat v_w = (CGRectGetWidth(self.frame) - (count_row - 1)*margin)/count_row;
 for (; i<count_row; i++) {
 UIView *view = [[UIView alloc]initWithFrame:CGRectMake(i*(margin+v_w), 0, v_w, CGRectGetHeight(self.frame))];
 view.backgroundColor = [UIColor blueColor];
 [self.contentView addSubview:view];
 }
}
@end
#import "ViewController.h"
#import "reuseview/ReuseViewCell.h"
#import "reuseview/ReuserCellCell.h"
#import "reuseview/ReuseAllCell.h"
#import "reuseview/ReuseAllView.h"
​
#define UseCell ReuseAllCell
​
@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic, strong)UICollectionView *colletionView;
@end
​
@implementation ViewController
​
- (void)viewDidLoad {
 [super viewDidLoad];
 [self.view addSubview:self.colletionView];
}
​
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
 return 1;
}
​
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
 return 5000;
}
​
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
 UseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([UseCell class]) forIndexPath:indexPath];
 if ([cell respondsToSelector:@selector(updateView)]) {
 [cell performSelector:@selector(updateView)];
 }
 return cell;
}
​
- (UICollectionView *)colletionView {
 if (!_colletionView) {
 UICollectionViewFlowLayout *flowlayout = [[UICollectionViewFlowLayout alloc]init];
 flowlayout.scrollDirection = UICollectionViewScrollDirectionVertical;
 flowlayout.minimumLineSpacing = 0.;
 flowlayout.minimumInteritemSpacing = 0.;
 flowlayout.estimatedItemSize = CGSizeZero;
 flowlayout.itemSize = CGSizeMake(self.view.frame.size.width/3, self.view.frame.size.width/3);
 _colletionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:flowlayout];
 _colletionView.backgroundColor = [UIColor whiteColor];
 [_colletionView registerClass:[UseCell class] forCellWithReuseIdentifier:NSStringFromClass([UseCell class])];
 _colletionView.delegate = self;
 _colletionView.dataSource = self;
 }
 return _colletionView;
}
​
@end

滑动到最底部,再滑动到最顶部,性能反馈如下:

image
  1. 全部使用复用cell。

    UIColloctionView返回总共15000个cell。每个cell宽屏幕的1/30。长屏幕的1/3。

    代码表述如下:

    #import "ReuseAllCell.h"
    ​
    @implementation ReuseAllCell
    - (instancetype)initWithFrame:(CGRect)frame {
     if (self = [super initWithFrame:frame]) {
     self.backgroundColor = [UIColor orangeColor];
     }
     return self;
    }
    @end
    #import "ViewController.h"
    #import "reuseview/ReuseViewCell.h"
    #import "reuseview/ReuserCellCell.h"
    #import "reuseview/ReuseAllCell.h"
    #import "reuseview/ReuseAllView.h"
    ​
    #define UseCell ReuseAllCell
    ​
    @interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
    @property (nonatomic, strong)UICollectionView *colletionView;
    @end
    ​
    @implementation ViewController
    ​
    - (void)viewDidLoad {
     [super viewDidLoad];
     [self.view addSubview:self.colletionView];
    }
    ​
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
     return 1;
    }
    ​
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
     return 5000*3;
    }
    ​
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
     UseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([UseCell class]) forIndexPath:indexPath];
     if ([cell respondsToSelector:@selector(updateView)]) {
     [cell performSelector:@selector(updateView)];
     }
     return cell;
    }
    ​
    - (UICollectionView *)colletionView {
     if (!_colletionView) {
     UICollectionViewFlowLayout *flowlayout = [[UICollectionViewFlowLayout alloc]init];
     flowlayout.scrollDirection = UICollectionViewScrollDirectionVertical;
     flowlayout.minimumLineSpacing = 0.;
     flowlayout.minimumInteritemSpacing = 0.;
     flowlayout.estimatedItemSize = CGSizeZero;
     flowlayout.itemSize = CGSizeMake(self.view.frame.size.width/30, self.view.frame.size.width/3);
     _colletionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:flowlayout];
     _colletionView.backgroundColor = [UIColor whiteColor];
     [_colletionView registerClass:[UseCell class] forCellWithReuseIdentifier:NSStringFromClass([UseCell class])];
     _colletionView.delegate = self;
     _colletionView.dataSource = self;
     }
     return _colletionView;
    }
    ​
    @end

滑动到最底部,再滑动到最顶部,性能反馈如下:

image

可以从视频上看出:无论从CPU峰值还是,RAM的占用情况,全部复用cell的性能都比复用cell再嵌套view的性能要差一些。

  1. cell中的子View,使用addSubView和removeFormSuperView来控制子View显示与隐藏

    UICollectionView总共返回5000个cell。

    其中每个cell中嵌套500个view。

    代码表述如下:

    #import "ReuseViewCell.h"
    @interface ReuseViewCell ()
    @property (nonatomic, strong)NSMutableArray *views;
    @end
    @implementation ReuseViewCell
    - (instancetype)initWithFrame:(CGRect)frame {
     if (self = [super initWithFrame:frame]) {
     self.views = [NSMutableArray array];
     [self setUpView];
     }
     return self;
    }
    ​
    - (void)setUpView {
     if (self.views.count) {
     [self updateView];
     } else {
     for (NSInteger i = 0; i<500; i++) {
     UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
     view.backgroundColor = [UIColor redColor];
     [self.contentView addSubview:view];
     [self.views addObject:view];
     }
     }

    }
    ​
    - (void)updateView {
     [self.views makeObjectsPerformSelector:@selector(removeFromSuperview)];
     for (UIView *view in self.views) {
     [self.contentView addSubview:view];
     }
    }
    @end

滑动到最底部,再滑动到最顶部,性能反馈如下:

image
  1. cell中的子View,一次性addSubView,然后使用hidden属性,来控制子view显示与隐藏。

UICollectionView返回5000个cell,每个cell中嵌套500个view。

代码表述如下:

        #import "ReuserCellCell.h"
        @interface ReuserCellCell ()
        ​
        @end
        @implementation ReuserCellCell
        - (instancetype)initWithFrame:(CGRect)frame {
         if (self = [super initWithFrame:frame]) {
         [self setUpView];
         }
         return self;
        }
        ​
        - (void)setUpView {
         if (self.contentView.subviews.count) {
         [self updateView];
         } else {
         for (NSInteger i = 0; i<500; i++) {
         UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
         view.backgroundColor = [UIColor greenColor];
         [self.contentView addSubview:view];
         }
         }
        }
        ​
        - (void)updateView {
         [self.contentView.subviews makeObjectsPerformSelector:@selector(setHidden:) withObject:@(YES)];
         [self.contentView.subviews makeObjectsPerformSelector:@selector(setHidden:) withObject:@(NO)];
        }
        @end

滑动到最底部,再滑动到最顶部,性能反馈如下:

image

从上述结果,可以很明显的看出,第一种方式比第二种方式,无论从cup使用率还是RAM的占用情况,都差了很多,并且,第一种方式,明显造成了页面卡顿。

于此同时,在代码中,第一种方式的写法也会造成不必要的内存占用

综上所述,后续我们在使用复用机制的时候,例如日历,可以复用大cell然后嵌套子View去实现,并且,一定要一次性addSubView后再单独控制子view的显示。此种做法,对于性能的要求最小

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