性能优化

初级

使用 ARC 管理内存
合理使用 reuseIdentifier
尽量不要 View 设置为透明
避免过于庞大的 XIB
不要阻塞主线程
实例

在 ImageViews 中调整图片大小. 如果要在 UIImageView 中显示一个来自 bundle 的图片, 你应保证图片的大小和 UIImageView 的大小相同. 在运行中缩放图谱按是很耗费资源的, 特别是 UIImageView 嵌套在 UIScrollView 中的情况. 如果图片是从远端服务器加载的你不能控制图片的大小, 比如在下载器前调整到合适大小的话, 你可以再狭窄完成后, 最好是用 background thread, 缩放一次, 然后在 UIImageView中是用缩放后的图片
选择正确的Collection
Array: 有序的一组值. 使用 index 来 lookup 很快, 使用 value lookup 很慢, 插入/删除很慢
Dictionaries: 储存键值对, 用 key 来查找会很快
Sets: 无序的一组值. 用值来查找会快, 插入/删除很快.
打开 gzip 压缩. app 可能大连依赖于服务器资源, 问题是我们的目标是移动设备, 因此你就不能指望网络状况有多好. 减小文档的一个方式就是在服务端和你的 app 中打开 gzip. 这对于文字种种能有更高压缩率的数据来说会有更显著的效果. iOS 已经在 NSURLConnection 中默认支持了 gzip 压缩, 当然 AFNetworking 这些基于它的框架也是.
中级

重用和延迟加载(lazy load) Views
更多的View意味着更多的渲染, 也就是更多的 CPU的内存消耗, 对于那种嵌套了很多View 在UIScrollView 你变的 app 更是如此.
这里我们用到的技巧就是模仿 UITableView 和 UICollectionView 的操作: 不要一次创建所有的 subview, 二十当需要的时候才创建, 当他们完成使命, 就把他们放进一个可从用的队列中. 这样的话你就只需要在滚动发生的时候创建你的 views, 避免不划算的内存分配.
cache
一个极好的原则就是, 缓存所需要的, 也就是那些不大可能改变你当时需要经常读取的东西.
可以缓存的东西, 远端服务器的响应, 图片, 计算记过, UITableView 的行高.
NSCache 和 NSDictionary 类似, 不同的是系统回收内存的时候他会自动删掉它的内容.
权衡渲染方法. 性能还是 bundle保持合适的大小.
处理内存警告. 移除缓存, 图片objc和其他一些可以重新创建的 object 和 strong references.
重用大开销对象
一些 Object 的初始化很慢, 比如 NSDateFormatter 和 NSCalendar. 然而, 你又不可避免的需要使用它们, 比如从 JSON 或者 XML 中解析数据. 想要避免使用这个对象的瓶颈, 你就需要重用它们, 可以通过添加属性到你的 Calss 里或者创建今天变量实现.
避免反复处理数据. 在服务器端和客户端使用相同的数据结构很重要.
选择正确的数据格式. 解析JSON 会比 XML 更快一些, JSON 也通常更小更便于传输. 从iOS5起有了官方内奸的 JSON deserialization 就更加方便使用了. 但是 XML 也有 XML 的好处, 比如使用 SAX 来解析本地文件一样, 你不需要像解析 json 一样等到整个文档下载完成才开始解析. 当你处理很大的数据的时候就会极大的降低内存消耗和增加性能.
正确设定背景图片
全屏背景图, 在 View 中添加一个 UIImageView 作为一个子 View
只是某个小的 View 的背景图, 你就需要用 UIColor 的 colorWithPatternImage 来做了, 它会更快地渲染也不会花费很多内存.
减少使用 web 特性. 想要更高的性能你就要调整下你的 HTML 了, 第一件要做的事就是尽可能移除不必要的 JavaScript, 避免使用过大的框架. 能只用原生的 js 就更好了. 尽可能异步加载例如用户行为统计 script 这种不影响页面表达的 javaScript. 注意你使用的图片, 保证图片符合你使用的大小.
shadow Path. Core Animation 不得不现在后台得出你的图形并加好阴影然后渲染, 这个开销是很大的. 使用shadowPath 的话就避免了这个问题. 使用 shadow path 的话 iOS 就不必每次都计算如何渲染, 它使用一个预先计算好的路径. 但问题都是自己计算path的话可能在默写 View 中比较困难, 且每当 View 的 frame 变化的时候你都需要去update shadow path
优化 TableView
正确使用 reuseIdentifier 来重用 cell
尽量使所有的 View opaque, 包括 cell 自身
避免渐变, 图片缩放, 后台选人
缓存行高
如果 cell 内部的内容来自web, 使用异步加载, 缓存请求结果.
使用 shadowPath 来画阴影
减少 subviews 的数量
尽量不使用 cellForRowAtIndexPath: 如果你需要用到它, 只用一次然后缓存结果
使用正确的数据结构来存储数据
使用 towHeight, sectionFooterHeight 和 sectionHeaderHeight 来 设定固定的高, 不要请求delegate
选择正确的数据储存选项
NSUserDefaults: 很nice 也很便捷, 但是它只适用于小数据, 比如一些简单的布尔型的设置选项, 再大点你就要考虑其他方式了
XML 这种结构化档案: 总体来说, 你需要读取整个文件到内存里去解析, 这样是很不经济的, 适用 SAX 有事一个很麻烦的事情.
NSCoding: 也需要读取文件
在性能层面来说, SQLite 和 CoreData 是相似的, 他们的不同在于具体使用方法
Core Data 代表一个对象的 graph model, 但是 SQLite 就是一个 DBMS
Apple 在一般情况下建议使用 Core Data, 但是如果你有理由不使用它, 那么久去使用更加底层的 SQLite 吧
如果你使用 SQLite, 你就可以用FMDB 这个库来简化 SQLite 的操作, 这样你就不会花很多精力了解 SQLite 的 C API了
高级

加速启动时间. 快速打开app是很重要的, 特别是用户第一次打开它时, 对 app 来讲, 第一印象太重要了, 和人见面一样. 你能做的就是使它尽可能做更多的异步任务, 比如加载远端或者数据库数据, 解析数据. 避免过于庞大的 XIB, 因为他们是在主线程上加载的. 所以尽量使用没有这个问题的 StoryBoards. 一定要把设备从 Xcode 断奶来测试启动速度
使用 Autorelease Pool. NSAutoreleasePool 负责释放 block 中的 autoreleased Object. 一般情况下它会自动被 UIKit 调用. 但是有些情况下也需要手动穿吉他. 加入创建很多零食对象, 你会发现内存一直在减少直到这些对象被 release 的时候. 这是因为只有当 UIKit 用光了 autorelease pool 的时候 memory 才会被释放. 消息是你可以在自己的 @autoreleasepool 里创建临时的对象来避免这个行为.
选择是否缓存图片. 常见的从 bundle 中加载图片的方式有俩种, 一个是 imageNamed, 一个是 imageWithContentsOfFile,
imageNamed: 这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象如果它存在的话。如果缓存中没有找到相应的图片,这个方法从指定的文档中加载然后缓存并返回这个对象。因此imageNamed的优点是当加载时会缓存图片。所以当图片会频繁的使用时,那么用imageNamed的方法会比较好。例如:你需要在 一个TableView里的TableViewCell里都加载同样一个图标,那么用imageNamed加载图像效率很高。系统会把那个图标Cache到内存,在TableViewCell里每次利用那个图像的时候,只会把图片指针指向同一块内存。正是因此使用imageNamed会缓存图片,即将图片的数据放在内存中,iOS的内存非常珍贵并且在内存消耗过大时,会强制释放内存,即会遇到memory warnings。而在iOS系统里面释放图像的内存是一件比较麻烦的事情,有可能会造成内存泄漏。例如:当一个UIView对象的animationImages是一个装有UIImage对象动态数组NSMutableArray,并进行逐帧动画。当使用imageNamed的方式加载图像到一个动态数组NSMutableArray,这将会很有可能造成内存泄露。原因很显然的。
imageWithContentsOfFile:仅加载图片,图像数据不会缓存。因此对于较大的图片以及使用情况较少时,那就可以用该方法,降低内存消耗。
避免日期格式的转换. 如果你要用 NSDataFormatter 来处理很多日期格式, 应该小心一点. 就像之前提到的, 任何时候重用 NSDateFormatters 都是一个好的时间. 如果你可以控制你所处理的日期格式, 今年选择 Unix 时间戳. 你可以方便的从时间戳转换到 NSDate

  • (NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {
    return[NSDate dateWithTimeIntervalSince1970:timestamp];
    }
    这样会比用 C 来解析日期字符串还快, 需要注意的是, 许多 web PAI 会以未免的形式返回时间戳, 因为这种格式在 javascript 中更方便使用. 记住用 dateFromUnixTimestamp 之前除以 1000 就可以了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,198评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,334评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,643评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,495评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,502评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,156评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,743评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,659评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,200评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,282评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,424评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,107评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,789评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,264评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,798评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,435评论 2 359

推荐阅读更多精彩内容