实现自定义NSOperation

新手学习整理, 小弟不才, 如有错误请指定! 一起学习.

在多任务编程中使用NSOperation时, 除了其子类NSInvocationOperation和NSBlockOperation之外, 还可以自定义子类继承NSOperation.
要做的任务很简单, 重载下面这个函数

- (void)main

官方文档:

The default implementation of this method does nothing. You should override this method to perform the desired task. In your implementation, do not invoke super. This method will automatically execute within an autorelease pool provided by NSOperation, so you do not need to create your own autorelease pool block in your implementation.

If you are implementing a concurrent operation, you are not required to override this method but may do so if you plan to call it from your custom start method.

我们要做的事情就是将任务封装到重载的main函数中.

接下来我用最最简单的方式演示从网络上下载两张图片的demo.(UI设置部分省略)

新建一个继承NSOperation的子类SYOperation

实现自定义NSOperation_第1张图片
SYOperation.png

其中定义了一个协议OperationDelegate, 因为这个类生成的对象要与ViewController这个对象进行通信传值.


接下来要在重载的main函数中加入要执行的任务, 这里我用GCD封装的任务.

#import "SYOperation.h"
static NSString * const image1 = @"http://cimage.tianjimedia.com/uploadImages/2016/09/20160916181734689.jpg";
static NSString * const image2 = @"http://upload-images.jianshu.io/upload_images/2353624-611338b00993c7ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240";
@implementation SYOperation
/**
 *  自定义的operation要把任务放到main函数中
 */
- (void)main {
    NSLog(@"进入main函数---%@",[NSThread currentThread]);
    //这里我创建了一个队列组, 用来在执行两个图片文件加载结束之后打印出加载完成
    dispatch_group_t groupOperaiton = dispatch_group_create();
    dispatch_group_async(groupOperaiton,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       
        NSLog(@"image1线程---%@",[NSThread currentThread]);
       
        NSURL *imageURL1 = [[NSURL alloc] initWithString:image1];
        NSData *imageData1 = [[NSData alloc] initWithContentsOfURL:imageURL1];
        NSInteger tag1 = 1;
        if (imageData1) {
            NSLog(@"I got imageData1!!!");
            dispatch_async(dispatch_get_main_queue(), ^{
                if ([self.delegate respondsToSelector:@selector(imageData:withTag:)]) {
                    [self.delegate imageData:imageData1 withTag:tag1];
                }
            });
        }
    });
    dispatch_group_async(groupOperaiton,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      
        NSLog(@"image2线程---%@",[NSThread currentThread]);
       
        NSURL *imageURL2 = [[NSURL alloc] initWithString:image2];
        NSData *imageData2 = [[NSData alloc] initWithContentsOfURL:imageURL2];
        NSInteger tag2 = 2;
        if (imageData2) {
            NSLog(@"I got imageData2!!!");
            dispatch_async(dispatch_get_main_queue(), ^{
                if ([self.delegate respondsToSelector:@selector(imageData:withTag:)]) {
                    [self.delegate imageData:imageData2 withTag:tag2];
                }
            });
        }
    });
    
    dispatch_group_notify(groupOperaiton, dispatch_get_main_queue(), ^{
        NSLog(@"加载图片任务完成!");
    });
}
@end


在ViewController中实现加载图片按钮的动作事件函数:

- (void) tapAction:(UIButton *)sender {
    //如果两个imageView的image已经有值, 单击按钮直接return.
    if (self.imageView1.image && self.imageView2.image) {
        return;
    }
    SYOperation *myOperation = [[SYOperation alloc] init];
    myOperation.delegate = self;
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSLog(@"当前线程 -- %@",[NSThread currentThread]);
    //放到队列里就会自动开启一条新线程去执行任务.
    [queue addOperation:myOperation];
}

实现代理方法:

- (void)imageData:(NSData *)data withTag:(NSInteger)tag{
    switch (tag) {
        case 1:
            [self.imageView1 setImage:[[UIImage alloc] initWithData:data]];
            NSLog(@"iamgeView1 load finish");
            break;
        case 2:
            [self.imageView2 setImage:[[UIImage alloc] initWithData:data]];
            NSLog(@"iamgeView2 load finish");
            break;
        default:
            break;
    }
}

控制台输出结果:

实现自定义NSOperation_第2张图片
输出结果.png

可以看出这些任务都是在不同的线程中执行的, 这样会加快执行速度, 但是要记住并不是开越多的线程就越好, CPU快速调度时会消耗大量的资源.


模拟器结果:

模拟器结果.gif

你可能感兴趣的:(实现自定义NSOperation)