NSOperation

2018-10-31  本文已影响17人  heart_领

一、NSOperation
NSOperation 和 NSOperationQueue 实现多线程的具体步骤:
程序员
先将需要执行的操作封装到一个 NSOperation 对象中
然后将 NSOperation 对象添加到 NSOperationQueue 中
系统
系统会自动将 NSOperationQueue 中的 NSOperation 取出来
将取出的 NSOperation 封装的操作放到一条新线程中执行

生命周期与状态
start 并发
Main
cancel
executing
finished
concurrent
asynchronous
ready

threadPriority & qualityOfService 服务质量 代表有更多几率被调度

completionBlock 回调监听
addExecutionBlock 添加执行代码块
waitUntilFinished 等待完成—回不来报错

addDependency 添加依赖(就能顺序执行,注意循环)
removeDependency 移除依赖
二、自定义NSOperation

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef void(^KCCompleteHandle)(NSData *imageData,NSString *kc_urlString);

@interface KCWebImageDownloadOperation : NSOperation

@property (nonatomic, assign) NSInteger kc_maxConcurrentOperationCount;

- (instancetype)initWithDownloadImageUrl:(NSString *)imageUrlString completeHandle:(KCCompleteHandle)completeHandle title:(NSString *)title;
@end

#import "KCWebImageDownloadOperation.h"
#import "NSString+KCAdd.h"

@interface KCWebImageDownloadOperation()
@property (nonatomic, readwrite, getter=isExecuting) BOOL executing;
@property (nonatomic, readwrite, getter=isFinished) BOOL finished;
@property (nonatomic, readwrite, getter=isCancelled) BOOL cancelled;
@property (nonatomic, readwrite, getter=isStarted) BOOL started;
@property (nonatomic, strong) NSRecursiveLock *lock;
@property (nonatomic, copy) NSString *urlString;
@property (nonatomic, copy) KCCompleteHandle completeHandle;
@property (nonatomic, copy) NSString *title;

@end

@implementation KCWebImageDownloadOperation
// 因为父类的属性是Readonly的,重载时如果需要setter的话则需要手动合成。
@synthesize executing = _executing;
@synthesize finished = _finished;
@synthesize cancelled = _cancelled;

- (instancetype)initWithDownloadImageUrl:(NSString *)urlString completeHandle:(KCCompleteHandle)completeHandle title:(NSString *)title{
    if (self = [super init]) {
        _urlString = urlString;
        _executing = NO;
        _finished  = NO;
        _cancelled = NO;
        _lock      = [NSRecursiveLock new];
        _completeHandle = completeHandle;
        _title = title;
    }
    return self;
}

- (void)start{

    @autoreleasepool{
        [_lock lock];
        
        self.started = YES;
        [NSThread sleepForTimeInterval:1.5];
        NSLog(@"下载 %@",self.title);
        if (self.cancelled) {
            NSLog(@"取消下载 %@",self.title);
            return;
        }
        NSURL   *url   = [NSURL URLWithString:self.urlString];
        NSData  *data  = [NSData dataWithContentsOfURL:url]; // 这里不完美 等到后面写网络 直接写在task里面 网络请求的回调里面
        if (self.cancelled) {
            NSLog(@"取消下载 %@",self.title);
            return;
        }
        if (data) {
            NSLog(@"下载完成: %@",self.title);
            [data writeToFile:[self.urlString getDowloadImagePath] atomically:YES];
            [self done];
            self.completeHandle(data,self.urlString);
        }else{
            NSLog(@"下载图片失败");
        }
        [_lock unlock];
    }
}

- (void)done{
    self.finished = YES;
    self.executing = NO;
}

/**
 取消操作的方法 --- 需要进行判断
 */
- (void)cancel{
    
    [_lock lock];
    if (![self isCancelled]) {
        [super cancel];
        self.cancelled = YES;
        if ([self isExecuting]) {
            self.executing = NO;
        }
        if (self.started) {
            self.finished = YES;
        }
    }
    [_lock unlock];
}

#pragma mark - setter -- getter

- (BOOL)isExecuting {
    [_lock lock];
    BOOL executing = _executing;
    [_lock unlock];
    return executing;
}

- (void)setFinished:(BOOL)finished {
    [_lock lock];
    if (_finished != finished) {
        [self willChangeValueForKey:@"isFinished"];
        _finished = finished;
        [self didChangeValueForKey:@"isFinished"];
    }
    [_lock unlock];
}

- (BOOL)isFinished {
    [_lock lock];
    BOOL finished = _finished;
    [_lock unlock];
    return finished;
}

- (void)setCancelled:(BOOL)cancelled {
    [_lock lock];
    if (_cancelled != cancelled) {
        [self willChangeValueForKey:@"isCancelled"];
        _cancelled = cancelled;
        [self didChangeValueForKey:@"isCancelled"];
    }
    [_lock unlock];
}

- (BOOL)isCancelled {
    [_lock lock];
    BOOL cancelled = _cancelled;
    [_lock unlock];
    return cancelled;
}
- (BOOL)isConcurrent {
    return YES;
}
- (BOOL)isAsynchronous {
    return YES;
}

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    if ([key isEqualToString:@"isExecuting"] ||
        [key isEqualToString:@"isFinished"] ||
        [key isEqualToString:@"isCancelled"]) {
        return NO;
    }
    return [super automaticallyNotifiesObserversForKey:key];
}
@end
上一篇下一篇

猜你喜欢

热点阅读