App调优建议

App调优
1.避免UIImageView不必要的拉伸 :

如果要在UIImageView中显示一个来自bundle的图片,你应保证图片的大小和UIImageView的大小相同。在运行中缩放图片是很耗费资源的,特别是UIImageView嵌套在UIScrollView中的情况下。

如果图片是从远端服务加载的你不能控制图片大小,比如在下载前调整到合适大小的话,你可以在下载完成后,最好是用background thread,缩放一次,然后在UIImageView中使用缩放后的图片。

2.尽量使用不透明的views

3.耗时操作多用子线程

4.集合类使用的注意点

Array:有序的一组值。使用index来查找很快,使用value 查找很慢, 插入/删除很慢。
Dictionaries:存储键值对,用键来查找比较快。
Sets: 无序的一组值。用值来查找很快,插入/删除很快。
5.压缩传输数据

减少带宽
使用高效的数据交换格式
在可能的情况下使用预先压缩的数据,对音频,视频,图像进行压缩或者按比例缩放。
压缩每一个请求与响应负载。压缩文本负载以减少带宽。
最简单的方式就是在服务端和你的app中打开gzip。这对于文字这种能有更高压缩率的数据来说会有更显著的效用。

6.重用和延迟加载(lazy load) Views

更多的view意味着更多的渲染,也就是更多的CPU和内存消耗,对于那种嵌套了很多view在UIScrollView里边的app更是如此。
这里我们用到的技巧就是模仿UITableView和UICollectionView的操作: 不要一次创建所有的subview,而是当需要时才创建,当它们完成了使命,把他们放进一个可重用的队列中。

维护一个重用的队列关键点:

  1. 维护一个重用队列
  2. 当元素离开可见范围时候,removeFromSuperView并加入重用队列
  3. 当需要加入新元素时,先尝试从重用队列获取可重用的元素并且从重用队列移除
  4. 如果队列为空,新建元素。

实际使用中,需要注意的点是:

当重用对象为 view controller 时,记得 addChildeViewController
当 view 或 view controller 被重用但其对应 model 发生变化的时候,需要及时清理重用前留下的内容
数据可以适当做缓存,在重用的时候尝试从缓存中读取数据甚至之前的状态(如 table view 的 contentOffset),以得到更好的用户体验
当 on screen 的元素数量可确定的时候,有时候可以提前 init 这些元素,不会在 scroll 过程中遇到因为 init 开销带来的卡顿(尤其是以 view controller 为重用对象的时候)
7.多做Cache
一个极好的原则就是,缓存所需要的,也就是那些不大可能改变但是需要经常读取的东西。我们能缓存些什么呢?一些选项是,远端服务器的响应,图片,甚至计算结果,比如UITableView的行高。

8.正确处理内存警告

一旦系统内存过低,iOS会通知所有运行中app。在官方文档中是这样记述:

如果你的app收到了内存警告,它就需要尽可能释放更多的内存。最佳方式是移除对缓存,图片object和其他一些可以重创建的objects的strong references.

幸运的是,UIKit提供了几种收集低内存警告的方法:

在app delegate中使用applicationDidReceiveMemoryWarning: 的方法
在你的自定义UIViewController的子类(subclass)中覆盖didReceiveMemoryWarning
注册并接收 UIApplicationDidReceiveMemoryWarningNotification 的通知
一旦收到这类通知,你就需要释放任何不必要的内存使用。

例如,UIViewController的默认行为是移除一些不可见的view, 它的一些子类则可以补充这个方法,删掉一些额外的数据结构。一个有图片缓存的app可以移除不在屏幕上显示的图片。

9.重用大开销对象

一些objects的初始化很慢,比如NSDateFormatter和NSCalendar。然而,你又不可避免地需要使用它们,比如从JSON或者XML中解析数据。

想要避免使用这个对象的瓶颈你就需要重用他们,可以通过添加属性到你的class里让后使用懒加载或者创建静态变量来实现。(静态变量内存属于全app,类似于单例)

10.设定Shadow Path
如何在一个View或者一个layer上加一个shadow呢,QuartzCore框架是很多开发者的选择:

// Setup the shadow ... 
UIView *view = [[UIView alloc] init]; 
view.layer.shadowOffset = CGSizeMake(-1.0f, 1.0f); 
view.layer.shadowRadius = 5.0f; view.layer.shadowOpacity = 0.6;

用起来简单但是不是最好的处理方式,Core Animation不得不先在后台得出你的图形并加好阴影然后才渲染,这开销是很大的。

使用shadowPath的话就避免了这个问题:

view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];

使用shadow path的话iOS就不必每次都计算如何渲染,它使用一个预先计算好的路径。但问题是自己计算path的话可能在某些View中比较困难,且每当view的frame变化的时候你都需要去update shadow path.

11.优化tableView
– 正确使用reuseIdentifier来重用cells

尽量使所有的view opaque,包括cell自身
避免渐变,图片缩放
缓存行高
如果cell内现实的内容来自web,使用异步加载,缓存请求结果
使用shadowPath来画阴影
减少subviews的数量
尽量不适用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后缓存结果
使用正确的数据结构来存储数据
使用rowHeight, sectionFooterHeight 和 sectionHeaderHeight来设定固定的高,不要请求delegate,如果是动态计算,建议同样做缓存处理。

12.选择正确的数据存储选项

缓存从业务角度可以分成两种:

按需缓存:类似浏览器,允许查看访问过的内容,可以缓存转换后的模型或者缓存url的返回值
预缓存:需要一个后台线程访问并以有意义的格式保存,以便可以在本地编辑。在有网时候把变更发到服务器。实现预缓存必须定期删除不在需要的过时数据,避免缓存不断增长。同步变更是通过追踪变更集并发送回服务器实现的。
一个App选择哪种缓存方式:是否需要在下载数据后做后期处理。后期处理包括:1.用户的编辑产生,2.更新下载数据。如重写html页面的图片链接指向本地缓存图片。

不建议用CoreData等来实现按需缓存,CoreData优势是不用反归档完整的数据就可以独立访问模型属性。而按需缓存并不需要独立访问模型属性。

当存储大块数据时你会怎么做?
你有很多选择,比如:

使用NSUerDefaults:适合小数据
使用XML, JSON, 或者 plist :你需要读取整个文件到内存里去解析,这样是很不经济的。使用SAX又是一个很麻烦的事情。
使用NSCoding存档
使用类似SQLite的本地SQL数据库
使用 Core Data

13.非必需条件下少用imageName:

然而,在图片反复重用的情况下imageNamed是一个好得多的选择。

如果你要加载一个大图片而且是一次性使用,那么就没必要缓存这个图片,用imageWithContentsOfFile足矣,这样不会浪费内存来缓存它。

那么我们应该如何选择呢?

UIImage *img = [UIImage imageNamed:@"myImage"]; // caching

UIImage *img = [UIImage imageWithContentsOfFile:@"myImage"]; // no caching

14.恰当的时候使用autorelease来避免产生内存峰值

没有加autorelease以下代码会把array里的image一口气加在到内存里面,而释放的时机是在这一次runloop结束,用autorelease包裹起来,内存释放时机为出了autorelease的时候。具体可以看黑幕背后的Autorelease

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,127评论 25 707
  • 写在前面本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS...
    升级打怪啊怪阅读 600评论 1 6
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,140评论 30 470
  • 最近有两条关于“免费到收费”的消息比较吸睛: 第一条,网上听歌要收费。CCTV2对话栏目上,专门搞了一栏音乐界大咖...
    余娜阅读 840评论 4 3
  • 一 枫叶又红了 又是一年西风凋碧树,落了一院如掌红艳。树下的人轻拂了衣襟,过后一身又满,却不再见那人拂袖,他就这般...
    青袍阅读 574评论 0 4