IOS 自定义Operation(下载功能)
一个下载操作就交给一个HMDownloadOperation对象
HMDownloadOperation.h / .m
@class HMDownloadOperation; @protocol HMDownloadOperationDelegate <NSObject>
@optional
- (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image;
@end @interface HMDownloadOperation : NSOperation
@property (nonatomic, copy) NSString *url;
@property (nonatomic, strong) NSIndexPath *indexPath;
@property (nonatomic, weak) id<HMDownloadOperationDelegate> delegate;
@end
#import "HMDownloadOperation.h" @implementation HMDownloadOperation /**
* 在main方法中实现具体操作
*/
- (void)main
{
@autoreleasepool { NSURL *downloadUrl = [NSURL URLWithString:self.url];
NSData *data = [NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时
UIImage *image = [UIImage imageWithData:data]; if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象
[self.delegate downloadOperation:self didFinishDownload:image];
});
}
}
}
控制器View 调用
@interface HMViewController () <HMDownloadOperationDelegate>
@property (nonatomic, strong) NSArray *apps;
@property (nonatomic, strong) NSOperationQueue *queue;
/** key:url value:operation对象 */
@property (nonatomic, strong) NSMutableDictionary *operations; /** key:url value:image对象*/
@property (nonatomic, strong) NSMutableDictionary *images;
@end @implementation HMViewController - (NSArray *)apps
{
if (!_apps) {
NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]]; NSMutableArray *appArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
HMApp *app = [HMApp appWithDict:dict];
[appArray addObject:app];
}
_apps = appArray;
}
return _apps;
} - (NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
_queue.maxConcurrentOperationCount = ; // 最大并发数 == 3
}
return _queue;
} - (NSMutableDictionary *)operations
{
if (!_operations) {
_operations = [NSMutableDictionary dictionary];
}
return _operations;
} - (NSMutableDictionary *)images
{
if (!_images) {
_images = [NSMutableDictionary dictionary];
}
return _images;
} - (void)viewDidLoad
{
[super viewDidLoad]; } #pragma mark - 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.apps.count;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"app";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
} HMApp *app = self.apps[indexPath.row];
cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download; // 显示图片
// 保证一个url对应一个HMDownloadOperation
// 保证一个url对应UIImage对象 UIImage *image = self.images[app.icon];
if (image) { // 缓存中有图片
cell.imageView.image = image;
} else { // 缓存中没有图片, 得下载
cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"]; HMDownloadOperation *operation = self.operations[app.icon];
if (operation) { // 正在下载
// ... 暂时不需要做其他事 } else { // 没有正在下载
// 创建操作
operation = [[HMDownloadOperation alloc] init];
operation.url = app.icon;
operation.delegate = self;
operation.indexPath = indexPath;
[self.queue addOperation:operation]; // 异步下载 self.operations[app.icon] = operation;
}
} // SDWebImage : 专门用来下载图片
return cell;
} #pragma mark - HMDownloadOperationDelegate
- (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image
{
// 1.移除执行完毕的操作
[self.operations removeObjectForKey:operation.url]; if (image) {
// 2.将图片放到缓存中(images)
self.images[operation.url] = image; // 3.刷新表格
[self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone]; // 3.将图片写入沙盒
// NSData *data = UIImagePNGRepresentation(image);
// [data writeToFile:@"" atomically:<#(BOOL)#>];
} } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// 开始拖拽
// 暂停队列
[self.queue setSuspended:YES];
} - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
[self.queue setSuspended:NO];
} @end
IOS 自定义Operation(下载功能)的更多相关文章
- iOS多线程自定义operation加载图片 不重复下载图片
摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用: 2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验 2:自定义operati ...
- iOS开发中文件的上传和下载功能的基本实现-备用
感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传 ...
- ios开发视频播放后台下载功能实现 :1,ios播放视频 ,包含基于AVPlayer播放器,2,实现下载,iOS后台下载(多任务同时下载,单任务下载,下载进度,下载百分比,文件大小,下载状态)(真机调试功能正常)
ABBPlayerKit ios开发视频播放后台下载功能实现 : 代码下载地址:https://github.com/niexiaobo/ABBPlayerKit github资料学习和下载地址:ht ...
- iOS彩票项目--第五天,新特性引导页的封装、返回按钮的自定义、导航控制器的滑动返回以及自定义滑动返回功能
一.上次实现了在AppDelegate中通过判断app版本决定是否进入新特性页面,今天将AppDelegate中的一坨进行了封装.将self.window的根控制器到底应该为新特性界面,还是主页面,封 ...
- iOS项目开发常用功能静态库
YHDeveloperTools iOS项目开发常用功能静态库 查看源码 功能方法: 1.字符检查 [NSString checkStringWithType:Email andTargetStrin ...
- iOS 自定义转场动画
代码地址如下:http://www.demodashi.com/demo/12955.html 一.总效果 本文记录分享下自定义转场动画的实现方法,具体到动画效果:新浪微博图集浏览转场效果.手势过渡动 ...
- iOS自定义转场动画实战讲解
iOS自定义转场动画实战讲解 转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerA ...
- iOS之开发支付功能概述
前言:本随笔将对IOS开发的支付功能进行一个概述. 内容大纲: 一.常见的支付方案简介 二.第三方支付SDK 三.苹果官方支付方案 四.Web支付方案 正文: 一.常见的支付方案简介 在微信支付中 微 ...
- IOS开发之支付功能概述
前言:本随笔将对IOS开发的支付功能进行一个概述. 内容大纲: 一.常见的支付方案简介 二.第三方支付SDK 三.苹果官方支付方案 四.Web支付方案 正文: 一.常见的支付方案简介 在微信支付中 微 ...
随机推荐
- 关于Django在写小项目的一些小注意事项
个人常踩的坑的小问题: . 在筛选元素的时候,及时queryset里面只有一个元素,取值还是要用方法取出来 例:#当狗指定pd时候已经唯一,还是要加fir()方法,本人经常忘记了 models.Boo ...
- delphi 与 java 兼容的 MD5
function GetMd5(AValue : string) : string; var md5 : TIdHashMessageDigest5; bytes,byte1 : TBytes; be ...
- spring boot mysql 事务
mysql默认 事务自动提交.即:每条insert/update/delete语句,不需要程序手工提交事务,而是mysql自行提交了. 如果我们想实现程序事务提交,需要事先关闭mysql的自动提交事务 ...
- my01_Mysql router 安装
Mysql router 主要用途是读写分离,主主故障自动切换,负载均衡,连接池等.安装如下 下载地址:https://dev.mysql.com/downloads/router/ tar -zxv ...
- js apply和call
apply()和call()这两个方法的作用是一样的,都是在特定作用域中调用函数,等于设置函数体内this对象的只,以扩充函数赖以运行的作用域 apply:方法能劫持另外一个对象的方法,继承另外一个对 ...
- forEach与map
一.原生js forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...
- 转 Celery 使用
http://www.mamicode.com/info-detail-1798782.html https://blog.csdn.net/lu1005287365/article/details/ ...
- Robot Framework自动化测试(一)
=============所需要环境========== Python: https://www.python.org/ RF框架是基于python 的,所以一定要有python环境. Robot f ...
- 性能测试工具LoadRunner01-性能测试基础
什么是性能测试? 在一定的约束条件下(指定的软件.硬件.网络环境等)对产品按一定的性能指标进行测试,确定系统能承受的最大负载压力,解决性能瓶颈.给用户最好的体验. 性能测试流程? 什么时候开始性能测试 ...
- 解决 eclipse cdt 运行时控制台乱码解决
1 点击黑色 倒三角 按钮 选择 run configurations 2 2.1 点击new 添加 LANG = en_US 2.2 选择 replace native environment wi ...