iOS开发笔记之TableView优化

 

TableView相信只要是作iOS开发的就不会陌生,目前大多数iOS的app都是采用TabBar+NavigationBar+TableViewController这一主流框架,android

既然用的这么频繁,确定就会在开发过程当中碰到一些问题--好比屏幕掉帧、卡顿等现象。这些现象大幅度的下降了用户的性能体验,并提升了crash的频率。程序员

所以如何能优化好tableView就很是考验程序猿们的功底了。性能优化

本猿~啊呸,只要开发公司项目的时候就会遇到这类问题,当快速滑动tableView而且cell中有大量图片和其余控件须要加载时,就会出现严重掉帧(通常公司的项目当时大量采用xib如今逐渐用手写代码代替),有时还会crash。因为当时项目比较赶进度,因此没有时间去优化性能,这种状况直到功能基本完善为止,花了大量功夫进行性能优化。
接下来我会根据tableView的delegate以及dataSource方法的执行顺序进行一步一步的讲解。服务器

首先当一个tableView须要显示内容的时候,首先会发送网络请求,向服务器请求数据,而后将数据转为咱们可使用的model后进行reload操做,接下来会向delegate和网络

dataSource请求数据。这时候会先调用- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 这个方法(假设section为1)。根据app

model获取cell的行数而后调用-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath,根据model计算出cell的高度。因为框架

tableView是继承自scrollView,因此tableView也会有contentSize属性。它的contentSize取决于全部cell的高度和。和scrollView有一点不一样,tableView只会管理可视的cell高度,这样作的目的是避免没必要要的性能开销。异步

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

这个代理方法的实现,在可见的页面是会重复绘制页面的,因此绝大部分人都会在这里作一些代码处理
好比:oop

static NSString *CellIdentifier = @"LazyTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  很常规的,防止cell对象无限的被建立,等同于android里面适配器的方法性能

以上举例代码是可让cell被重复使用,通常大概只会在可见页面部分的几个cell会被建立下,其余的所有重复使用前面已经有的cell对象,到时候只要填充数据就能够了

那么仅仅只是如此,恐怕如今的cell自定义的页面不仅是文本那么简单,多多少少都会带有一些图片吧,当你下滑时候是否发现有那么一点点的卡顿现成,特别是网络很差,并且仍是在iPhone4上跑的就会更明显了

那么在cell里面异步加载图片是个程序员都会想到,可是若是你给每一个循环对象都加上异步加载,而且下滑的时候,这一操做将会被执行,虽然是异步,可是一个app里面的线程过多也会卡顿的,特别是在下滑操做的时候给每一个图片进行异步加载。

那么这里能够利用UIScrollViewDelegate代理很好的解决这问题:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

能够识别tableview禁止或者减速滑动结束的时候进行异步加载图片。

如下方法来执行异步加载操做:

 //获取可见部分的对象
       NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
        for (NSIndexPath *indexPath in visiblePaths)
        {
           //获取的dataSource里面的对象,而且判断加载完成的不须要再次异步加载
             <code>
        }

同时在cell绘制中也作限制

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

         if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
            {
               //开始异步加载图片
                <code>
            }

tableview 中止滑动的时候开始异步加载图片

最后也别忘记在内存紧张的状况下释放调全部的异步线程,以保证的你的app不会被系统强制关闭

- (void)didReceiveMemoryWarning{
//  释放调异步加载图片的线程以及全部图片资源对象
<code>
}

还有千万别忘记销毁的时候手动把全部的使用到的代理设置nil。

 

还有一个利用线程和Runloop延迟加载图片的新思路:

[self.avatarImageView performSelector:@selector(serImage:)    
                        withObjetc:downloadedImage
                        afterDelay:0
                        inModes:@[NSDefaultRunLoopMode]]
 + (NSThread *)networkRequestThread {
      static NSThread *_networkRequestThread = nil;
      static dispatch_once_t oncePredicate;
      dispatch_once(&oncePredicate, ^{
      _networkRequestThread =
      [[NSThread alloc] initWithTarget:self
           selector:@selector(networkRequestThreadEntryPoint:)
           object:nil];
      [_networkRequestThread start];
 });

 return _networkRequestThread;
相关文章
相关标签/搜索