iOS多线程之9.自定义NSOperation
本文主要讲如何自定义NSOperation,以及自定义NSOperation的一些注意事项,以下载图片为例。
新建一个类,继承于NSOperation。
CustomOperation.h 代码
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface CustomOperation : NSOperation @property (nonatomic, copy) NSString *strURL; @property (nonatomic, copy) void (^DownLoadImageBLock)(UIImage *image); @end
CustomOperation.m
#import "CustomOperation.h" @implementation CustomOperation // 1.实现Main方法 - (void)main { // 2.新建一个自动释放池 @autoreleasepool { // 3.正确响应取消事件 if (self.isCancelled) return; NSURL *url = [NSURL URLWithString:self.strURL]; NSData *data = [NSData dataWithContentsOfURL:url]; if (self.isCancelled) { url = nil; data = nil; } UIImage *image = [UIImage imageWithData:data]; if (self.isCancelled) { image = nil; return; } // 4.把图片传回主线程 dispatch_async(dispatch_get_main_queue(), ^{ //5. 用block传值 if (self.DownLoadImageBLock) { self.DownLoadImageBLock(image); } }); } } // 6. dealloc -(void)dealloc { NSLog(@"operation-------dealloc"); }
分析:1.自定义NSOperation都要实现Main方法,在这个方法里写要NSOperation执行的耗时操作。 2.新建一个自动释放池。如果是异步操作,不能访问主线程的自动释放池,所以要新建一个。 3.正确响应取消事件。在每一个耗时操作之前,都要判断此操作是否被取消。如果取消了,就不往下执行了。因为我们有时候需要先取消下载,例如滑动tableView的时候,等不滑动了,再继续,增加UI流畅度。 4.把图片传回主线程。主线程回调,因为下载完的数据肯定是要操作UI的,AFNetworking就是这样干的。 5.用block传值。传值之前判断是否存在此block,这和代理传值之前判断代理是否响应了代理里的方法是一个道理。 6.dealloc方法,监测一下有没有正确释放内存。
使用自定义NSOperation
代码
// 点击屏幕下载图片 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 1.创建一个CustomOperation对象 CustomOperation *operation1 = [[CustomOperation alloc] init]; // 2.为URL赋值 operation1.strURL = @"http://h.hiphotos.baidu.com/zhidao/pic/item/6d81800a19d8bc3ed69473cb848ba61ea8d34516.jpg"; // 3.处理block传回来的结果 operation1.DownLoadImageBLock = ^(UIImage *image) { self.imageView1.image = image; }; // 4.创建一个CustomOperation对象 CustomOperation *operation2 = [[CustomOperation alloc] init]; operation2.strURL = @"http://h.hiphotos.baidu.com/zhidao/pic/item/0eb30f2442a7d9334f268ca9a84bd11372f00159.jpg"; operation2.DownLoadImageBLock = ^(UIImage *image) { self.imageView2.image = image; }; // 5.创建一个队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 6.把操作放入队列中 [queue addOperation:operation1]; [queue addOperation:operation2]; }
效果
分析1. 这一步和使用系统提供的NSOperation没有区别。 2.为自定义的NSOperation提供下载地址。 3.处理下载之后的数据。由于在自定义的NSOperation中已经是主线程回调了,所以就可以直接操作UI了。 4.同上。 5.创建一个队列。 6..把操作放入队列中。 自定义一个NSOperation就是这么简单,我们只要重写main方法就可以,传值的方式有多种,如果大家不习惯block,也可以用代理,都能达到效果。但是block的可读性更高,因为代码都写在一起,好找。稍后我会向git上传一个项目,是列表页下载图片,用自定义NSOperation写的,有兴趣的可以看看。