多线程学习---解析苹果官网代码《LazyTableImages》

很早以前就看过《LazyTableImages》的代码,当时只是大致看了一下它的原理,没有很详细的研读。最近在看第三方开源框架的代码,学习优化策略以及优雅的代码风格,提高自身水平,希望与大家一起学习和共同讨论。

一、简要流程说明。   

1、通过RSS feed建立URL请求获取XML数据;

2、通过获取的XML数据,创建ParseOperation在后台使用NSXMLParser运行解析XML数据得到想要的数据存放在NSArray里面;

3、ParseOperation执行完后告诉table view在主线程上面重新加载数据;

4、当UITableViewCell不再滚动或拖动的时候,通过可见cells的indexPath在NSArray里面得到cells对应的每一个imageURLString,为每一个imageURLString创建一个IconDownloader下载图片,每一个IconDownloader下载完毕通过委托的方式为cell更新image。

二、详细流程讲解:

1.利用NSOperation队列异步解析RSS,ParseOperation执行完成,通知主线程重新加载数据,更新UI,主要代码如下:

 NSOperation的相关知识可以查看http://blog.csdn.net/jasonjwl/article/details/50992720

_parser = [[ParseOperation alloc] initWithData:data];
__weak LazyTableAppDelegate *weakSelf = self; //避免循环引用的常用做法 
self.parser.completionBlock = ^(void) { if (weakParser.appRecordList != nil) { 
//确保主线程更新UI dispatch_async(dispatch_get_main_queue(), ^{ 
RootViewController *rootViewController = (RootViewController*)[(UINavigationController*)weakSelf.window.rootViewController topViewController]; 
rootViewController.entries = weakParser.appRecordList; 
//当解析完成后告诉table view刷新数据 [rootViewController.tableView reloadData]; }); } 
// 当解析完成后,将队列置为nil 
weakSelf.queue = nil; 
}; 
[self.queue addOperation:self.parser]; // 开始执行解析

 
 1.1 ParseOperation开始解析,会调用文件ParseOperation.m中的main方法,将解析后的结果存储在appRecordList数组 
 
- (void)main
{
    _workingArray = [NSMutableArray array];
    _workingPropertyString = [NSMutableString string];
    //利用NSXMLParser解析XML
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:self.dataToParse];
    [parser setDelegate:self];
    [parser parse];
    if (![self isCancelled])
    {
        // 将解析结果保存在appRecordList
        self.appRecordList = [NSArray arrayWithArray:self.workingArray];
    }
    self.workingArray = nil;
    self.workingPropertyString = nil;
    self.dataToParse = nil;
}
2.解析XML完成后,赋值rootViewController.entries = weakParser.appRecordList;通过Block回调通知rootViewController.tableView进行更新。

2.1 在加载cell的时候,做了相应优化 ,如下所示:

  • 当等待cell加载的时候,添加占位cell
  • 当没有缓存images,只有等滚动停止的时候才会让下载器下载图片

  • 如果cellimage正在下载,则返回占位图片

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = nil;
    
    NSUInteger nodeCount = self.entries.count;
	
	if (nodeCount == 0 && indexPath.row == 0)
	{
        // add a placeholder cell while waiting on table data
        //当等待cell加载的时候,添加占位cell
        cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier forIndexPath:indexPath];
    }
	else
    {
        //重用cell
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        if (nodeCount > 0)
        {   
            //将每一行cell跟app关联起来
            AppRecord *appRecord = (self.entries)[indexPath.row];
            cell.textLabel.text = appRecord.appName;
            cell.detailTextLabel.text = appRecord.artist;
            
            //当没有缓存images,只有等滚动停止的时候才会让下载器下载图片
            if (!appRecord.appIcon)
            {
                if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
                {
                    [self startIconDownload:appRecord forIndexPath:indexPath];
                }
               
                //如果cell的image正在下载,则返回占位图片
                cell.imageView.image = [UIImage imageNamed:@"Placeholder.png"];                
            }
            else
            {
               cell.imageView.image = appRecord.appIcon;
            }
        }
    }
    
    return cell;
}
2.2 只有当滚动停止时才加载可见cell的图片

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate)
	{
        [self loadImagesForOnscreenRows];
    }
}
2.3 当图片已下载完成时,要避免重复下载

- (void)loadImagesForOnscreenRows
{
    if (self.entries.count > 0)
    {
        NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
        for (NSIndexPath *indexPath in visiblePaths)
        {
            AppRecord *appRecord = (self.entries)[indexPath.row];
            
            if (!appRecord.appIcon)
            // Avoid the app icon download if the app already has an icon
            {
                [self startIconDownload:appRecord forIndexPath:indexPath];
            }
        }
    }
}

思考:1.如果图片为圆角图片,该如何优化?

           2.除了上述提了的一些优化cell方法,还有那些优化cell的方法。

  欢迎大家交流讨论!如有不对的地方,请指出,谢谢!本人正在找iOS方面的工作,如有合适的职位请跟我联系,谢谢

          后续我将带来MJExtension和SDWebImage源码解析系列

           LazyTableImages的下载地址:https://developer.apple.com/library/ios/samplecode/LazyTableImages/Introduction/Intro.html








你可能感兴趣的:(多线程学习---解析苹果官网代码《LazyTableImages》)