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