本文介绍: iOS-UIKit浅谈

参考博客

[iOS开发]UIKit
iOS离屏渲染

CALayer和UIView

区别

UIView继承UIResponder,主要负责事件传递事件响应属于基于UIKit框架
CALayer继承NSObject负责图像渲染动画视图显示属于QuartzCore框架

而且这两大内容都符合单一职责原则,单一职责通俗地讲就是一个类只做一件事。

虽然CALayer没有事件响应能力,但是我们可以通过

关系

    CALayer *grayCover = [[CALayer alloc] init];
    grayCover.backgroundColor = [[UIColor greenColor] CGColor];
    grayCover.position = CGPointMake(200,200);
    grayCover.bounds = CGRectMake(0,0,80,80);
    [self.view.layer addSublayer:grayCover];

可以看到会在目标view对应位置将白色改为了绿色
请添加图片描述
没有添加新图层,而是在原本view上改变颜色,这和addsubview并不一样。

这三棵树的逻辑结构都是一样的,区别只是有各自的属性

tableview

tableView遵循的两个delegate

tableView对于iOS开发者来说是无人不知无人不晓

下面我们复习一下tableView需要完成的操作

具体到方法:

这三个方法都是dataSource协议中的方法,我们往往通过这三个方法实现数据显示

//控制行数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
//控制组数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
//cell编辑函数
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

两个常用的方法是delegate中的方法,提供某些交互方法:

//控制行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
//cell点击事件函数
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

tableView复用机制

iOS-tableViewCell的重用机制
iOS UITableviewCell的重用机制(这位大佬对于cell重用理解的非常到位)

自己实验中对cell的重用总结如下

自定义cell

  1. 一次加载创建tableView时候,是屏幕上最多可以显示几行cell就先创建几个cell,此时复用池里什么没有
  2. 开始下滑tableView,刚开始滑动时由于第一行没有完全滑出屏幕进复用池时下面新cell已经显示到屏幕上了,所以下方这个新划出来的cell就是创建cell而不是复用cell复用时也得看新加载cell复用池中的备用cell有没有同类型id,没有就不复用),然后接着滑动第一个cell就完全出屏幕进入复用池了,下面我们接着滑动,接着那个需要新显示出来的cell如果和复用池中我们保存第一个cell是同种id,如果是就直接拿来复用,如果不是就新创建判断是否能复用和新创建的操作都在cell编辑函数cellForRowAtIndexPath:中)。
  3. 上滑tableView和下滑原理基本一致,完全出屏幕的入复用池,需要加载到屏幕的cell的先看池中有没有同idcell,有了就复用,没有就创建

定义cell

  1. 一次加载创建tableView时候,是屏幕上最多可以显示几行cell就先创建几个cell,此时复用池里什么都没有
  2. 开始下滑tableView,刚开始滑动时由于第一行没有完全滑出屏幕进复用池时下面新cell已经显示到屏幕上了,所以下方这个新划出来的cell就是创建cell而不是复用的cell(复用时也得看新加载cell和复用池中的备用cell有没有同类型id,没有就不复用),然后接着滑动第一个cell就完全出屏幕进入复用池了,下面我们接着滑动,接着那个需要新显示出来的cell如果和复用池中我们保存第一个cell是同种id,如果是就直接拿来复用,如果不是就新创建(判断是否能复用和新创建的操作都在cell编辑函数cellForRowAtIndexPath:中)。
  3. 上滑tableView和下滑原理基本一致,完全出屏幕的入复用池,需要加载到屏幕的cell的先看池中有没有同idcell,有了就复用,没有就创建。

其实定义和非自定义cell的复用情况都是一样的。
下面我们讲一个使用cell需要注意的点:

tableView自适应高度

关于自适应高度,主要思路两个

下面我们就进行一下这两个实现思路讲解
先说第二个吧,我认为这个方法既然是新技术,那么就一定能帮我们更好使用tableView

AutoLayout自适应高度

主要思路就是两步

  1. 使用AutoLayout方法
  2. 不要实现heightForRowAt方法

如何使用AutoLayout方法?

AutoLayout是一种自动布局技术,可以帮我们自动实现布局苹果官方推荐开发者尽量使用AutoLayout布局UI界面

其实就是两个核心概念参考约束

听起来很像我们的Masonry的使用,确实,使用Masonry完成自适应高度是很舒服的,直接使用其约束条件,不用我们自己手动实现各种约束条件

以自定义cell中的Label自动展开为例

使用自适应高度代码如下

- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   
    if ([reuseIdentifier isEqualToString:@"11"]) {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        [self layoutIfNeeded];
    } else {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        [self layoutIfNeeded];
    }
    
    return self;
}

- (void) layoutSubviews {
    [super layoutSubviews];
    [self.contentView addSubview:_labelTest];
    [_labelTest mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_labelTest.superview.mas_top).offset(10.0);
        make.bottom.equalTo(_labelTest.superview.mas_bottom).offset(-10);
        make.left.equalTo(_labelTest.superview.mas_left).offset(10.0);
        make.right.equalTo(_labelTest.superview.mas_right).offset(-10.0);
    }];
}

正常使用一个Masonry应该怎么实现呢?很简单,给topleftsize,这三个条件就足以用最简单方式实现一个布局操作,而自适应高度的话最后一个最接近底部控件就得写上其距底部的高度,就是四个边,上左下右给了界限,中间的高度自己根据自己的内容的高度自己实现,达到将cell撑开效果

另外,我们在用masonry实现自适应label展开时也得注意一个点,就是labelnumberOfLines需要设置0,这个就是对label行数不做限制

这基本上就是AutoLayout的设置部分,还有一个重点的东西:[self layoutIfNeeded];,这行代码为什么得手动写一遍?其实这涉及到了一个东西:“自动展开的MasonrylayouSubviews不起作用问题”,这是因为iOS10之前,layoutSubViews方法在一种cell初始化时就会调用两次,而iOS10之后,其只会调用一次,就导致我们需要手动补上那一次,就能够控件得到正确展开,这时候有人可能要问为什么平时没有注意到?其实是因为每种cell初始化时候都会调用一次,我们平时项目中一般都是多种类型cell定义,每种初始化调用layoutSubViews方法相当于把上一种cell所缺的一次补上了,然后自己又缺了一次,但是如果我们最后一种不是需要自适应展开的就没有问题,但如果是需要自适应展开的就会导致它无法展开,也是因为我们平时项目中最后一种cell往往不是要展开的,所以不会注意到这个问题。

有一个小细节就是要实现cell自适应展开时就不要去写heightForRow方法了,否则就不会按照自适应来,关于自适应需要配置的东西各iOS版本区别如下:
请添加图片描述
而现在iOS14以后,包括15、16,这两个配置都不需要写了,因为rowHeight默认值UITableViewAutomaticDimension苹果官方文档介绍如下:
请添加图片描述
翻译版如下:
请添加图片描述

可以看到为什么不能自适应时去写heightForRow方法了,里面写的清清楚楚,如果实现了heightForRow方法,tableView视图就会忽视自适应属性的配置

详细layoutSubViews方法问题可以详见该博客iOS10后使用Masonry进行自动布局出现的问题及处理述

大佬Self-Sizing进行了一些优化,详见该博客iOS Self-Sizing的一点优化
另外还有一个不用Masonry版本iOS之SelfSizing Cell-高度自动计算详细讲解(就是用数组存一下自己手动预设好的layout布局数组包含上左下右四个位置信息的设置,然后添加到了NSLayoutConstraint去显示,具体操作非常的秀)

下面展示一些代码实例:
本人上方写的label自适应展开的代码的各种情况如下:
如果写为(我们注释掉最后一种celllayoutIfNeeded方法调用):
注:例子的前5cell是一种,后5cell是一种。

- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   
    if ([reuseIdentifier isEqualToString:@"11"]) {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        [self layoutIfNeeded];
    } else {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        //[self layoutIfNeeded];
    }
    
    return self;
}

- (void) layoutSubviews {
    [super layoutSubviews];
    [self.contentView addSubview:_labelTest];
    [_labelTest mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_labelTest.superview.mas_top).offset(10.0);
        make.bottom.equalTo(_labelTest.superview.mas_bottom).offset(-10);
        make.left.equalTo(_labelTest.superview.mas_left).offset(10.0);
        make.right.equalTo(_labelTest.superview.mas_right).offset(-10.0);
    }];    
}

运行结果如下:请添加图片描述
可以看到我们最后一种cell并没有得到自适应展开

然后我们又修改代码为如下(恢复最后一种celllayoutIfNeeded方法调用):

- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   
    if ([reuseIdentifier isEqualToString:@"11"]) {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        [self layoutIfNeeded];
    } else {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        [self layoutIfNeeded];
    }
    
    return self;
}

- (void) layoutSubviews {
    [super layoutSubviews];
    [self.contentView addSubview:_labelTest];
    [_labelTest mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_labelTest.superview.mas_top).offset(10.0);
        make.bottom.equalTo(_labelTest.superview.mas_bottom).offset(-10);
        make.left.equalTo(_labelTest.superview.mas_left).offset(10.0);
        make.right.equalTo(_labelTest.superview.mas_right).offset(-10.0);
    }];    
}

运行效果如下:
请添加图片描述
可以看到我们的最后一种cell也是成功自适应展开了。

接着我们又来修改一种操作(去掉layoutSubviews方法中[super layoutSubviews]调用父类同名方法):

- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   
    if ([reuseIdentifier isEqualToString:@"11"]) {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        [self layoutIfNeeded];
    } else {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        [self layoutIfNeeded];
    }
    
    return self;
}

- (void) layoutSubviews {
	[super layoutSubviews];
    [_labelTest mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_labelTest.superview.mas_top).offset(10.0);
        make.bottom.equalTo(_labelTest.superview.mas_bottom).offset(-10);
        make.left.equalTo(_labelTest.superview.mas_left).offset(10.0);
        make.right.equalTo(_labelTest.superview.mas_right).offset(-10.0);
    }];    
}

运行结果如下:
请添加图片描述
我们看到最后一种cell确实是展开了,但是仔细看和上一种情况还是有一些区别的,该区别就是本次的每行cell背后的背景色都是透明的,而上次的cell是有默认的白色背景分割线效果的,这也许就是layoutSubviews方法原来默认的一些实现,不过都是小细节上的处理

最后我们再展示一种(将label布局不写在layoutSubviews方法里,而是直接写在cell的编辑函数cellForRowAtIndexPath:里,而且我们去掉了每种cell初始化时调用的[self layoutIfNeeded]):

//cell自定义的两个函数
- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   
    if ([reuseIdentifier isEqualToString:@"11"]) {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        //[self layoutIfNeeded];
    } else {
        _labelTest = [[UILabel alloc] init];
        _labelTest.numberOfLines = 0;
        [self.contentView addSubview:_labelTest];
        //[self layoutIfNeeded];
    }
    
    return self;
}

- (void) layoutSubviews {
    [super layoutSubviews];
}


//cell的编辑函数
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    if (indexPath.row < 5) {
        TestCell *cell = [_tableViewTest dequeueReusableCellWithIdentifier:@"11" forIndexPath:indexPath];

        if (cell == nil) {
            cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"11"];
        }
        
        cell.labelTest.text = @"111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
        
    [cell.labelTest mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(cell.labelTest.superview.mas_top).offset(10.0);
        make.bottom.equalTo(cell.labelTest.superview.mas_bottom).offset(-10);
        make.left.equalTo(cell.labelTest.superview.mas_left).offset(10.0);
        make.right.equalTo(cell.labelTest.superview.mas_right).offset(-10.0);
    }];
    
        return cell;
    } else {
        
        TestCell *cell = [_tableViewTest dequeueReusableCellWithIdentifier:@"12" forIndexPath:indexPath];

        if (cell == nil) {
            cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"12"];
        }
        
        cell.labelTest.text = @"222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222";
        
        [cell.labelTest mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(cell.labelTest.superview.mas_top).offset(10.0);
            make.bottom.equalTo(cell.labelTest.superview.mas_bottom).offset(-10);
            make.left.equalTo(cell.labelTest.superview.mas_left).offset(10.0);
            make.right.equalTo(cell.labelTest.superview.mas_right).offset(-10.0);
        }];
        
        return cell;
    }
}

运行结果如下:
请添加图片描述
可以看到也是可以自适应展开的。

这种情况下如果不去掉[self layoutIfNeeded];这行代码的话,其效果也是一样的,因为layoutSubviews中已经没有关于label布局约束的代码了,调不调没啥影响,主要是看layoutSubviews中有没有写[super layoutSubviews];,写的话cell默认就有白背景和分割线,不写的话就是一个透明背景,别的细节修饰都没有。

手动计算高度,进行存储

两种方法:

sizeToFit
    UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(10,100, 350, 0)];
    label.numberOfLines = 0;
    label.text =@"当前视图的边界边界大小的变化123123213213213123123123123123213213123213213213123123213";
    NSLog(@"the label bounds : %@",NSStringFromCGRect(label.frame));
    [label sizeToFit];
    NSLog(@"%f",label.frame.size.height);
    [self.view addSubview:label];

这个例子我们通过设置label.numberOfLines = 0;[label sizeToFit]; 就可以保证其可以自动换行成为合适的位置,在sizeToFit之后我们就可以得到其空间展开应有的高度。

运行效果和打印结果如下:
请添加图片描述
请添加图片描述
可以看到我们实现了label的自适应展开,而且sizeToFit的确成功算出了label应有的高度。

所以我们可以用sizeToFit方法计算出label应有的高度,然后存入数组中,在cell创建时在heightForRow方法中从数组取值加载合适的cell高度即可

boundingRectWithSize

详情参考博客iOS 计算字符串长度-boundingRectWithSize:

iOS 7.0之前用sizeWithFont:(计算的不是很准确):

CGFloat width1=[(NSString *)obj sizeWithFont:[UIFont systemFontOfSize:16] constrainedToSize:CGSizeMake(1000, FONTHEIGHT)].width;

iOS 7.0之后用 boundingRectWithSize:
返回文本绘制所占据的矩形空间

CGRect rect=[(NSString *)obj boundingRectWithSize:CGSizeMake(1000, FONTHEIGHT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size.width;

里面参数如下:

下面我们展示一个使用的例子:

    UILabel * labelSecond = [[UILabel alloc] init];
    labelSecond.numberOfLines = 0;
    labelSecond.text =@"当前视图的边界边界大小的变化123123213213213123123123123123213213123213213213123123213";
    labelSecond.font = [UIFont systemFontOfSize:16];
	//用我们预设的width来算label应该显示的size   
    CGRect rectTest = [labelSecond.text boundingRectWithSize:CGSizeMake(350, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil];
    
    //从刚才算的size中取出heigth
    //加1是怕四舍五入完之后少了一点导致显示的label少了一行
    CGFloat titleHeight = ceilf(rectTest.size.height) + 1;
    
    //用算出来的结果显示label
    labelSecond.frame = CGRectMake(10,200, 350, titleHeight);
    //将label作为子视图添加到父视图
    [self.view addSubview:labelSecond];

运行结果如下:
请添加图片描述
可以看到实现了label的自适应展开,与sizeToFit同理,添加到数组中,在cell创建时调用heightForRow方法中从数组取值加载合适的cell高度即可

在使用boundingRectWithSize计算label高度时有几个需要注意的点,且该方法计算label高度很容易出问题,做好一下几点就基本不会出问题了:

  • 计算前设置好label字体大小,不能设置的17,算的16,这样很容易就会失去最后一行甚至多行的显示。
  • 在计算完成之后,我们需要用ceilf方法来取需要的高度或者宽度,但是由于这个过程会发生四舍五入,所以有可能差的小数部分导致最后一行的label无法显示,所以算出来之后给结果加1,就可以避免这个问题。

什么时候tableview相比于scrollerView,tableview做了哪些别的操作

给一个UIScrollerViw实现UITableView

详情参考该博客:ScrollView + 自定义cell 组合(实现复用)

collectionview

collectionView的使用详见:
自定义UICollectionViewLayout实现
iOS UICollectionView基础

UIViewController的生命周期

参考该博客:[iOS]-ViewController生命周期

frame、bounds

frame相对于父视图自己的位置bounds是自己的起始位置。其有两个属性,sizeoriginorigin初始都为0(如果设置了setBounds就不是0),setBounds中前两个变量为负数是什么意思?为何(-30,-30)偏移量,却可以让view向右下角移动呢?

这是因为setBounds的作用是:强制将自己(view1坐标系的左上角点,改为(-30,-30)。那么view1的原点,自然就向在右下方偏移(30,30)

这里Inset也是同样道理,-50,-50rect坐标origin)按照(dx,dy) 进行平移,然后将rect大小size) 宽度缩小2倍的dx,高度缩小2倍的dy

举个例子:所以inset 值为正,缩小,值为负,放大

setBounds

    UIView *viewFirst = [[UIView alloc] init];
    viewFirst.frame = CGRectMake(100, 100, 200, 200);
    //对viewFirst设置setBounds
    [viewFirst setBounds:CGRectMake(-30, -30, 200, 200)];
    
    viewFirst.backgroundColor = [UIColor blueColor];
    
    NSLog(@"111=%@", NSStringFromCGRect(viewFirst.frame));
    
    [self.view addSubview:viewFirst];
    
    UIView *viewSecond = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];

    viewSecond.backgroundColor = [UIColor yellowColor];
   
    NSLog(@"111=%@", NSStringFromCGRect(viewSecond.frame));
    
    [viewFirst addSubview:viewSecond];

运行效果如下:
请添加图片描述
可以看到我们通过对viewFirst设置setBounds,使得所为viewFirst子视图的viewSecond的位置发生了偏移

其实setBounds写为:setBounds:CGRectMake(-30, -30, 200, 200)就是强制viewFirst坐标系的左上角点改为(-30, -30),原本没有设置setBounds的话是(0, 0),而我们viewSecondframe为:(0 0 200 200); ,所以就需要找到viewFirst上的对应(0, 0)位置,由于此时的(0, 0)位置已不是viewFirst视图的左上角,而已经是viewFirst视图的左上角那个点向右和向下各平移30距离的那个点了,所以也就造成了我们看到的viewSecondviewFirst上是往右下平移了的。

打印结果的话发现
viewFirstframe为:(100 100 200 200);
viewSecondframe为:(0 0 200 200);

Inset

UIView *viewFirst = [[UIView alloc] init];
    viewFirst.frame = CGRectMake(100, 100, 200, 200);
    viewFirst.backgroundColor = [UIColor blueColor];
    
	NSLog(@"111=%@", NSStringFromCGRect(viewFirst.frame));
	
    [self.view addSubview:viewFirst];
    
    //在viewFirst的frame基础上进行了Inset设置
    CGRect rect = CGRectInset(viewFirst.frame , -10, -10);
    UIView *viewSecond = [[UIView alloc] initWithFrame:rect];
    viewSecond.backgroundColor = [UIColor yellowColor];
    
    NSLog(@"111=%@", NSStringFromCGRect(viewSecond.frame));
    
    [self.view addSubview:viewSecond];

打印结果如下:
请添加图片描述
可以看到设置了CGRectInset(viewFirst.frame , -10, -10);之后,黄色的viewSecond的四个边角都扩展10长度

打印结果的话发现
viewFirstframe为:(100 100 200 200);
viewSecondframe变为了:(90 90 220 220);

UIViewController和UIResponder

我们最熟悉的UIApplicationUIViewUIViewController这几个类是直接继承UIResponderUIResponder类是专门用来应用户的操作处理各种事件(UIEvent)的。
UIResponder提供了用户点击按压检测(presses)以及手势检测(motion)的回调方法,分别对应用户开始、移动结束以及取消,其中只有在程序强制退出或者来电时,取消事件才会调用。

离屏渲染

On-Screen Rendering:当前屏幕渲染,指的是 GPU 的渲染操作是在当前用于显示的屏幕缓冲区中进行
Off-Screen Rendering:离屏渲染分为 CPU 离屏渲染和 GPU 离屏渲染两种形式。GPU 离屏渲染指的是 GPU 在当前屏幕缓冲区外新开辟一个缓冲区进行渲染操作

为什么会使用离屏渲染:
当使用圆角阴影遮罩的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所以就需要屏幕外渲染被唤起

GPU离屏渲染的代价很大:
离屏渲染之所以会特别消耗性能,是因为要创建一个屏幕外的缓冲区,然后从当屏缓冲区切换到屏幕外的缓冲区,然后再完成渲染;其中,创建缓冲区切换上下文最消耗性能,而绘制其实不是性能损耗的主要原因

上下文之间的切换这个过程的消耗会比较昂贵,涉及到 OpenGLpipelinebarrier,而且 offscreen-render 在每一帧都会涉及到,因此处理不当肯定会对性能产生一定的影响。另外由于离屏渲染会增加 GPU工作量,可能会导致 CPU+GPU 的处理时间超出 16.7ms,导致掉帧卡顿

详细的离屏渲染相关可以参考该博客:iOS离屏渲染

原文地址:https://blog.csdn.net/m0_52192682/article/details/126259409

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_36646.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注