手动布局(写宽高)和Autolayout(自动布局)性能的差别主要在子父视图添加到40个子视图的时候,才会显得区别。其他的话,性能之差很小 。
CPU使用于当视图加载的情况下的计算坐标,加载数据,逻辑的处理,绘制和渲染还有动画了这边的事情交给GPU去处理,gpu解压jpg/png图片的时候,gpu不能直接绘制,比较耗时间,必须先解压。
tableview的复用原理,他的设计模式是享元模式,享元模式的主要核心是:采用一个共享的资源来避免大量相同内容对象的开销,公共对象池,共享节能资源。
享元模式的概念
面向对象可以非常方便的解决一些扩展性的问题,但是在这个过程中系统务必会产生一些类或者对象,如果系统中存在对象的个数过多时,将会导致系统的性能下降。对于这样的问题解决最简单直接的办法就是减少系统中对象的个数。所谓享元模式就是运行共享技术有效地支持大量细粒度对象的复用。系统使用少量对象,而且这些都比较相似,状态变化小,可以实现对象的多次复用。共享模式是支持大量细粒度对象的复用,所以享元模式要求能够共享的对象必须是细粒度对象。
TableView复用时,总共会生成多少个cell?
一般会生成visibleCells+1,或者+2,+3都有可能,其实visibleCells就是去获取tableView的上所有的cell,他是一个数组集合,可以将它取出来放到自己的数组里,将它遍历可以得到你想要的对应cell。栗子:http://blog.csdn.net/xiaojiuxing_csdn/article/details/50470372
•参考tableView可以实现哪些常见自定义控件?
一般的话可以自定义一个滚动的空间。
tableView刷新优化
举个例子,比如当一个图片下载完成的时候,我才知道它的高度,然后我才去回掉reloadData的方法去刷新界面,如果它有十张图片,都是在0.1毫秒完成,我0.1秒就需要掉10次的reloadData,他和聊天信息一样,来一条信息就刷新一次,100条就刷新100次,1秒钟就刷新。所以可以优化它没有必要的reloadData这个方法。继续tableview的刷新优化,我们将用两个方法解决这个问题:
1.runloop来解决这个问题,平常我们滑动的 cell的时候,首先判断是否有图片,没有图片数据,将去下载图片,生成bitmp,缓存她的高度,然后用一个通知tablview去刷新,这是一个基本的逻辑原理,但是下面一段代码是主动区检查她的数据和高度
self.observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(),
kCFRunLoopBeforeWaiting, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity
activity) {
CFStringRef model = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent());
NSLog(@"%@",(__bridge NSString *) model);
CFRelease(model);
[weakSelf.indexs removeAllObjects];
NSArray *visibleCells = [weakSelf.tableView visibleCells];
for (EOCNewsTableViewCell *cell in visibleCells) {
if (fabs([cell.info rowHeight] - cell.frame.size.height) > 0.1) {
[weakSelf.indexs addObject:[weakSelf.tableView indexPathForCell:cell]];
}
}
if (weakSelf.indexs.count > 0) {
[EOCUtil runInMain:^{
NSLog(@"update Row");
[weakSelf.tableView reloadRowsAtIndexPaths:weakSelf.indexs
withRowAnimation:UITableViewRowAnimationFade];
}];
}
});
在viewDidLoad的时候,添加一个runloop的观察者,监听runloop挂前的状态,将runloop的空闲时间去刷新tabview,首先是在visibleCells取出对应的cell,搜集到它们的下标,然后缓存她的高度,通过它们缓存图片的高度减去cell本身的高度,大于0.1的时候,说明有图片的高度数据,然后通知他去刷新,这样就减少一些没有必要的刷新了。需要注意的是,当退出的时候将观察者移除。
2.还有一个一个方法,就是使用对应缓存一定时间内改变cell的状态高的行,然后一次性将它们刷新
runloop的基本概念
如果当一个线程需要下载图片的时候,等网络图片下载完成,才去刷新界面。这个不是一条下载任务的线程,这是一条等待下载完成回掉数据的线程。系统为了节约资源,会将这个线程挂起来。线程谁来唤醒,什么时候唤醒,就是交给runloop去唤醒这个线程,线程挂起之后,由runloop去接受事件,等runloop接到时间原之后,就将这个委托分给对应的线程,runloop开启的时候,他有两个model的模式:
1\. kCFRunLoopDefaultMode:默认mode
2\. UITrackingRunLoopMode:跟踪滚动事件UISCrollview
3\. kCFRunLoopCommonModes: 包括以上两个
runloop状态:即将开始,开始,执行,等待结束,结束
等线程的事情处理完之后,告诉等待状态中的runloop,继续将线程挂起,继续循环等待新的事件源。
缓存的优化
我们可以使用一个缓存的来优化性能的均衡。最简单就是sdiamge,相信只要开发ios的人都接触过着强大的第三方库。它的流程就是:
1.先检查url的合法性。
2.从内存中检查它是否有数据。
2.如有没有,将在磁盘中寻找数据。(注意,内存的读取数据是磁盘的100倍,以后或许会更大,尽量的减少I/O操作,因为扫描内存的数据,很耗时间也很耗性能)。
3.如果磁盘和内存都没有数据,判断它是否是最大的下载数量。
4.开启网络线程去下载图片数据,下载之后,将它的数据写入内存之中,如果数据大于150m,将写入磁盘之中。
5.下载完成之后判断是否有下一个下载的任务,如果有,将它添加到队列之中开启下载。
内存优化
1.imageName的优化,它一开始获取到图片的时候他不给你解压图片,一直到需要加载到界面的时候,它才会给你讲bitmp的数据解压出来,解压出来bitmp图片,如果bitmp 的数据大,它会自动帮你cache起来,如果你的应用对内存比较敏感,建议还是不要用imageName这个方法加载图片
2.可以利用自动释放池来优化内存。对象会在什么时候释放,当调用delloc的时候。延迟释放主要在mrc下可以进行去去使用,延迟释放是指当RetainCount ==0的时候,但是对象没有立即销毁,他没有调用delloc,因为延迟对象会被放入自动释放池中,当自动释放池销毁的时候,这些延迟对象会被relose掉,当它们的RetainCount=0的时候,它们才会被释放。栗子:当需要一个大量临时对象的时候,比如一个for的循环。可以添加一个释放池,在autoreleasepool池中创建这个临时对象,防止内存暴涨。autoreleasepool的创建有三个情况,runloop主线程创建的时候,比如appleDelage主函数;子线程runloop开启的时候;开启一个touchEvent点击事件的时候。
•1.为什么要使用栅格化
是对于ui变化不大的tablview进行,进行缓存,减少计算量,避免频繁的渲染,降低内存,提交性能。
•2.如何减少主线程任务
开启time检查性能。
•3.设计一个图片缓存库
参考sd
•4.如何显示一段长文本(文本内容假设10G)
可以使用预加载处理,然后进行缓存,或许分段加载,加载最前和最后一页。
•5.线程数量是不是越多越好。
线程过多不是过多更好,切换需要时间,消耗性能大