一、NSOperation
NSOperation 和 NSOperationQueue 實(shí)現(xiàn)多線程的具體步驟:
程序員
先將需要執(zhí)行的操作封裝到一個(gè) NSOperation 對(duì)象中
然后將 NSOperation 對(duì)象添加到 NSOperationQueue 中
系統(tǒng)
系統(tǒng)會(huì)自動(dòng)將 NSOperationQueue 中的 NSOperation 取出來
將取出的 NSOperation 封裝的操作放到一條新線程中執(zhí)行
生命周期與狀態(tài)
start 并發(fā)
Main
cancel
executing
finished
concurrent
asynchronous
ready
threadPriority & qualityOfService 服務(wù)質(zhì)量 代表有更多幾率被調(diào)度
completionBlock 回調(diào)監(jiān)聽
addExecutionBlock 添加執(zhí)行代碼塊
waitUntilFinished 等待完成—回不來報(bào)錯(cuò)
addDependency 添加依賴(就能順序執(zhí)行,注意循環(huán))
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
// 因?yàn)楦割惖膶傩允荝eadonly的,重載時(shí)如果需要setter的話則需要手動(dòng)合成。
@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]; // 這里不完美 等到后面寫網(wǎng)絡(luò) 直接寫在task里面 網(wǎng)絡(luò)請(qǐng)求的回調(diào)里面
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;
}
/**
取消操作的方法 --- 需要進(jìn)行判斷
*/
- (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