关于性能优化的一些经验

1.视图view优化 预处理和延时加载
2.UITableView优化
3.缓存优化 重用大开销对象。对于初始化很慢的对象通过添加属性的方式保持该对象,保证只被初始化一次,多次复用。如NSDataFormatter。
4.线程优化 合理的线程分配
5.内存优化 使用autorelease pool 降低内存峰值
6.代码细节优化 使用正确API 如果关键代码用C/C++效率更高就使用C/C++
7.图片优化

卡顿产生的原因和解决方案
在 VSync 信号到来后,系统图形服务会通过 CADisplayLink 等机制通知 App,App 主线程开始在 CPU 中计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。随后 CPU 会将计算好的内容提交到 GPU 去,由 GPU 进行变换、合成、渲染。随后 GPU 会把渲染结果提交到帧缓冲区去,等待下一次 VSync 信号到来时显示到屏幕上。由于垂直同步的机制,如果在一个 VSync 时间内,CPU 或者 GPU 没有完成内容提交,则那一帧就会被丢弃,等待下一次机会再显示,而这时显示屏会保留之前的内容不变。这就是界面卡顿的原因。

用 Instuments 的 GPU Driver 预设,能够实时查看到 CPU 和 GPU 的资源消耗。在这个预设内,你能查看到几乎所有与显示有关的数据,比如 Texture 数量、CA 提交的频率、GPU 消耗等,在定位界面卡顿的问题时,这是最好的工具。

CPU 资源消耗原因和解决方案
对象创建 延迟创建的时间 尽量放到缓存池里复用。
对象调整 尽量避免调整视图层次、添加和移除视图
对象销毁 尽量放到后台线程销毁
布局计算 不要频繁的计算和调整这些属性
Autolayout 用一些工具方法替代(比如常见的left/right/top/bottom/width/height 属性),或者使用 ComponentKit、AsyncDisplayKit 等框架
文本计算 NSAttributedString放到后台线程进行以避免阻塞主线程
文本渲染 CoreText排版和绘制
图片解码
图像绘制 后台异步绘制 CoreGraphic

GPU 资源消耗原因和解决方案
GPU 能干的事情比较单一:接收提交的纹理(Texture)和顶点描述(三角形),应用变换(transform)、混合并渲染,然后输出到屏幕上。
纹理渲染
视图混合
图形生成
CALayer 的 border、圆角、阴影、遮罩(mask),CASharpLayer 的矢量图形显示,通常会触发离屏渲染(offscreen rendering),而离屏渲染通常发生在 GPU 中。最彻底的解决办法,就是把需要显示的图形在后台线程绘制为图片,避免使用圆角、阴影、遮罩等属性。

UIView 和 CALayer 的关系:View 持有 Layer 用于显示,View 中大部分显示属性实际是从 Layer 映射而来;Layer 的 delegate 在这里是 View,当其属性改变、动画产生时,View 能够得到通知。UIView 和 CALayer 不是线程安全的,并且只能在主线程创建、访问和销毁。

圆角的问题(Offscreen rendering的问题)

离屏渲染是什么?

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

相比于当前屏幕渲染,离屏渲染的代价是很高的,主要体现在两个方面: 创建新缓冲区 要想进行离屏渲染,首先要创建一个新的缓冲区。 上下文切换 离屏渲染的整个过程,需要多次切换上下文环境:先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上有需要将上下文环境从离屏切换到当前屏幕。而上下文环境的切换是要付出很大代价的。哪些行为会导致Offscreen rendering?

custom drawRect: (any, even if you simply fill the background with color)
CALayer corner radius
CALayer shadow
CALayer mask
any custom drawing using CGContext

例如你的工程里的XXCell.m

- (void)setupViews {
   _textLabel = [[UILabel alloc]init];
   [_textLabel setTextAlignment:NSTextAlignmentCenter];
   _textLabel.font = [UIFont systemFontOfSize:14];
   [self.contentView addSubview:_textLabel];

   self.contentView.layer.masksToBounds = YES;
   self.contentView.layer.cornerRadius = 4;
}

这种写法导致了离屏渲染。

如何解决?

圆角使用UIImageView来处理。
简单来说,底层铺一个UIImageView,然后用GraphicsContext生成一张带圆角的图。

@implementation UIImage (RoundedCorner)

- (UIImage *)wt_imageWithRoundedCornersAndSize:(CGSize)sizeToFit andCornerRadius:(CGFloat)radius
{
     CGRect rect = (CGRect){0.f, 0.f, sizeToFit};

     UIGraphicsBeginImageContextWithOptions(sizeToFit, NO, UIScreen.mainScreen.scale);
     CGContextAddPath(UIGraphicsGetCurrentContext(),
                 [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius].CGPath);
     CGContextClip(UIGraphicsGetCurrentContext());

     [self drawInRect:rect];
     UIImage *output = UIGraphicsGetImageFromCurrentImageContext();

     UIGraphicsEndImageContext();

     return output;
}

@end

这样,就可以避免在大量cell离屏渲染的时候拖慢fps。
当然,如果只是一两个view有圆角的需求,你大可不必这么折腾。直接设置layer.cornerRadius就可以了。

设置圆角的方法也有很多种。

1.cornerRadius
2.UIBezierPath

- (void)drawRect:(CGRect)rect {
    CGRect bounds = self.bounds;
    [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:8.0] addClip];

    [self.image drawInRect:bounds];
}
3.maskLayer(CAShapeLayer) 相关链接:Applying Rounded Corners  http://articles.cocoahope.com/blog/2013/03/06/applying-rounded-corners

  Mastering UIKit performance  https://yalantis.com/blog/mastering-uikit-performance/

重载Autolayout的问题

- (void)refreshConstraints {
    [self.view setNeedsUpdateConstraints];
    [self.view updateConstraintsIfNeeded];
    [self.view layoutIfNeeded];
    [self.view setNeedsDisplay];
}

setNeedsUpdateConstraints 确保在未来的某个阶段updateConstraintsIfNeeded这个方法会调用 updateConstraints.
setNeedsLayout 确保在未来的某个阶段 layoutIfNeeded 这个方法会调用 layoutSubviews.
直接调用setNeedsUpdateConstraints去更新约束是很奇怪的,因为只有在某些情况下你的某个约束失效了,你需要移除它,这时候才需要直接调用这个方法。 stackoverflow链接
上面这个答案说的已经很好了,我只用翻译一边就好了。

主题色的问题

一个app的各种控件的颜色有很多种处理方法。
一般常见的有。

写成JSON文件,然后设置一个Category读取。
直接在UIColor的Category里设置各种方法获取相对应的颜色。
Raywenderlich的一篇相关文章
相对比使用最多的方法,比如这种。

[self.view setBackgroundColor:[UIColor colorWithHexString:@"F3F3F3"]];  
[_textLabel setTextColor:[UIColor colorWithHexString:@"969696"]];
self.contentView.backgroundColor = [UIColor clearColor];
self.contentView.layer.borderColor = [UIColor colorWithHexString:@"969696"].CGColor;            [_textLabel setTextColor:[UIColor colorWithHexString:@"009788"]];     self.contentView.backgroundColor = [UIColor clearColor];
self.contentView.layer.borderColor = [UIColor colorWithHexString:@"009788"].CGColor;

无法阅读,也不好改。
或者,用这个。

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

推荐阅读更多精彩内容