性能优化
UITableView的FooterView和HeaderVIew也可以使用reuseIdentifier的, 对于频繁显示的, 可以使用此方法来优化
尽量将不透明的View的Opaque的属性设置为YES, 对于手动创建的View尤其是在ScrollView中使用的, 尽量手动设置这个属性为YES, 系统会自动做一些渲染优化
尽量在Xib中少使用控件, 因为每一个Xib文件都会在程序运行的时候加载到内存中, 如果你的Xib中有很多的图片, 那样就会浪费很多的内存资源
UIImageView中的图片, 尽量手动进行一次缩放, 让他适应你的ImageView, 比如在图片下载之后, 缩放了该图片然后在使用, 否则会浪费一些不必要的资源
-
延迟加载View的两种方案:
- 先创建出来这个View, 但是将他设置为隐藏, 在需要用到的时候显示: 这个方案会在一开始的时候消耗内存, 但是由于已经创建出来了, 用户点击显示View只是更改属性, 并不会有卡顿感
- 当View需要使用的时候才创建: 这个方案比较节省内存, 但是如果对于那些响应需要很及时的View来说, 这个会有一丝的卡顿感
-
对于一些反复使用的数据, 尽量要缓存他:
- 可以使用NSCache来做缓存, 他会在系统受到内存警告的时候, 自动去释放
-
处理内存警告
- 当你的程序运行内存过大的时候, 会收到内存警告, 最佳的做法不是在控制器中使用
didReceiveMemoryWarning
- 在AppDelegate中, 使用
applicationDidReceiveMemoryWarning
方法 - 在你的控制器中, 注册并接受
UIApplicationDidReceiveMemoryWarningNotification
的通知, 然后执行相应的方法
- 当你的程序运行内存过大的时候, 会收到内存警告, 最佳的做法不是在控制器中使用
-
避免反复处理数据
- 如: 当你从服务器中获取到一组NSArray的数据的时候, 你应该避免反复的遍历或者转换这些数据, 以免造成不必要的内存消耗
-
关于View中的背景图片
- 在View中添加一个ImageView是最常规的做法, 他针对于一个大图作为背景, 最为节省内存
- 同时还有另一个方法就是:
[UIColor colorWithPatternImage:]
, 这个方法是专门用来使用小图平铺View来做背景图片的方法, 如果你有一个很小的图片, 想用它填充一个View, 那么这个是最好的做法, 他会更快的渲染到View中
-
View的阴影
- 最简单的方法是通过操作Layer来完成:
view.layer.shadowOffset = CGSizeMake(-1.0f, 1.0f);
, 但是这个方法会让系统先去计算你的图形, 然后添加阴影, 最后再进行渲染, 这样会造成额外的内存开销 - 另一个内存较为优化的方式是:
view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];
, 这个方法不必每次都去计算你的阴影, 但是需要自己计算这个path, 对于一些复杂样式的View以及经常发生改变的View, 还需要不停的更新
- 最简单的方法是通过操作Layer来完成:
-
UITableVIew的一些优化点
- 尽量使所有的子控件, 包括Cell本身, 都将Opaque设置为YES
- 尽量避免进行图片缩放等复杂操作, 如果必须的话, 请做缓存, 否则内存会飙升
- 如果cell的内容来自网络, 那么要使用异步加载, 然后做缓存
- 尽量使用
rowHeight, sectionFooterHeight, sectionHeaderHeight
来设置高度, 避免代理的重复设置
在程序启动的时候, 一定要尽量避免使用过大的XIB去构建界面, 因为他是放在主线程中去绘制的, 如果实在想用, 那么就要用StoryBoard, 同时注意主界面的数据一定要去后台加载
-
在for循环中, 如果需要反复的创建对象的话, 那么你就要使用
autoreleasepool
来避免内存的过度开销- 例如, for循环中, 反复的创建临时对象, 但是这些对象在你for循环之后就不需要使用了, 那么这时候就需要使用自动释放池来优化内存
-
选择是否缓存图片
imageNamed
和imageWithContentsOfFile
- 关于前者, 官方文档的解释为: 这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象如果它存在的话。如果缓存中没有找到相应的图片,这个方法从指定的文档中加载然后缓存并返回这个对象。
- 也就是说,
imageName
会缓存这个图片对象, 那么对于那种需要反复创建使用的图片, 就需要使用这个方法了 - 而后者, 只是单纯的加载图片, 当这个图片释放掉了, 那么就需要重新去创建, 无法从缓存中获取
- 因此, 对于那些图片较大, 只需要偶尔使用一次的东西, 就使用
imageWithContentsOfFile
吧