- 使用复用机制
- 尽可能设置 View 为不透明
- 避免臃肿的 XIB 文件
- 不要阻塞主线程
- 图片尺寸匹配 UIImageView
- 选择合适的容器
- 启用 GZIP 数据压缩
- View 的复用和懒加载机制
- 缓存服务器的响应信息(response)、图片、计算值。比如:UITableView 的 row heights。
- 关于图形绘制
- 处理 Memory Warnings
在 AppDelegate 中实现 - [AppDelegate applicationDidReceiveMemoryWarning:] 代理方法。
在 UIViewController 中重载 didReceiveMemoryWarning 方法。
监听 UIApplicationDidReceiveMemoryWarningNotification 通知。
- 复用高开销的对象
- 减少离屏渲染(设置圆角和阴影的时候可以选用绘制的方法)
- 优化 UITableView
通过正确的设置 reuseIdentifier 来重用 Cell。
尽量减少不必要的透明 View。
尽量避免渐变效果、图片拉伸和离屏渲染。
当不同的行的高度不一样时,尽量缓存它们的高度值。
如果 Cell 展示的内容来自网络,确保用异步加载的方式来获取数据,并且缓存服务器的 response。
使用 shadowPath 来设置阴影效果。
尽量减少 subview 的数量,对于 subview 较多并且样式多变的 Cell,可以考虑用异步绘制或重写 drawRect。
尽量优化 - [UITableView tableView:cellForRowAtIndexPath:] 方法中的处理逻辑,如果确实要做一些处理,可以考虑做一次,缓存结果。
选择合适的数据结构来承载数据,不同的数据结构对不同操作的开销是存在差异的。
对于 rowHeight、sectionFooterHeight、sectionHeaderHeight 尽量使用常量。
- 选择合适的数据存储方式
在 iOS 中可以用来进行数据持有化的方案包括:
NSUserDefaults。只适合用来存小数据。
XML、JSON、Plist 等文件。JSON 和 XML 文件的差异在「选择正确的数据格式」已经说过了。
使用 NSCoding 来存档。NSCoding 同样是对文件进行读写,所以它也会面临必须加载整个文件才能继续的问题。
使用 SQLite 数据库。可以配合 FMDB 使用。数据的相对文件来说还是好处很多的,比如可以按需取数据、不用暴力查找等等。
使用 CoreData。也是数据库技术,跟 SQLite 的性能差异比较小。但是 CoreData 是一个对象图谱模型,显得更面向对象;SQLite 就是常规的 DBMS。
- 减少应用启动时间
快速启动应用对于用户来说可以留下很好的印象。尤其是第一次使用时。
保证应用快速启动的指导原则:
尽量将启动过程中的处理分拆成各个异步处理流,比如:网络请求、数据库访问、数据解析等等。
避免臃肿的 XIB 文件,因为它们会在你的主线程中进行加载。重申:Storyboard 没这个问题,放心使用。
注意:在测试程序启动性能的时候,最好用与 Xcode 断开连接的设备进行测试。因为 watchdog 在使用 Xcode 进行调试的时候是不会启动的。
- 使用 Autorelease Pool (内存释放池)
- imageNamed 和 imageWithContentsOfFile
滑动UITableView时,按需加载对应的内容
//按需加载 - 如果目标行与当前行相差超过指定行数,只在目标滚动范围的前后指定3行加载。
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)];
NSIndexPath *cip = [[self indexPathsForVisibleRows] firstObject];
NSInteger skipCount = 8;
if (labs(cip.row-ip.row)>skipCount) {
NSArray *temp = [self indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y, self.width, self.height)];
NSMutableArray *arr = [NSMutableArray arrayWithArray:temp];
if (velocity.y<0) {
NSIndexPath *indexPath = [temp lastObject];
if (indexPath.row+33) {
[arr addObject:[NSIndexPath indexPathForRow:indexPath.row-3 inSection:0]];
[arr addObject:[NSIndexPath indexPathForRow:indexPath.row-2 inSection:0]];
[arr addObject:[NSIndexPath indexPathForRow:indexPath.row-1 inSection:0]];
}
}
[needLoadArr addObjectsFromArray:arr];
}
}
// 记得在tableView:cellForRowAtIndexPath:方法中加入判断:
if (needLoadArr.count>0&&[needLoadArr indexOfObject:indexPath]==NSNotFound) {
[cell clear];
return;
}
异步绘制
//异步绘制
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
CGRect rect = CGRectMake(0, 0, 100, 100);
UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor lightGrayColor] set];
CGContextFillRect(context, rect);
//将绘制的内容以图片的形式返回,并调主线程显示
UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// 回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
//code
});
});
网友评论