您的位置:首页 > 编程语言

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

2016-03-27 21:33 387 查看
很早以前就看过《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,只有等滚动停止的时候才会让下载器下载图片

如果cell的image正在下载,则返回占位图片

- (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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: