1) NSInvocationOperation和NSBlockOperation不能满足我们的需求时就需要我们自定义,自定义NSOperation的场景主要是为了我们能更好的控制一个任务,什么情况下开始、取消、完成, 并且可以分离代码的实现
2) 实现步骤:(可参考下面代码)
(1)实现start方法
(2)重写isAsynchronous,是否为并发任务、根据自己的情况即可
(3)main方法可根据自己的实际需要决定是否实现、一般实现并在里面做自己的事
(4)finished、executing更新任务的状态,用于触发KVO
(5)自己的任务完成后,一定要把当前的任务状态改为完成,否则队列中后面的任务,将永远不会执行
@property(assign, nonatomic, getter=isFinished) BOOL finished;
@property(assign, nonatomic, getter=isExecuting) BOOL executing;
@property(assign, nonatomic, getter=isStart) BOOL start;
@property(assign, nonatomic, getter=isFinished) BOOL finished;
@property(assign, nonatomic, getter=isExecuting) BOOL executing;
@property(assign, nonatomic, getter=isStart) BOOL start;
@implementation CustomOperation
@synthesize finished = _finished, executing = _executing;
- (BOOL)isAsynchronous {
return NO;
}
- (void)setFinished:(BOOL)finished {
[self willChangeValueForKey:@"finished"];
_finished = finished;
[self didChangeValueForKey:@"finished"];
}
- (void)setExecuting:(BOOL)executing {
[self willChangeValueForKey:@"executing"];
_executing = executing;
[self didChangeValueForKey:@"executing"];
}
- (void)start {
@synchronized (self) {
self.start = YES;
if (self.isCancelled) {
[self completed];
return;
}
@autoreleasepool {
[self main];
}
self.executing = YES;
}
}
- (void)main {//在此处做一些更复杂的操作
NSLog(@"准备开始执行任务啦~ %@", [NSThread currentThread]);
//模拟3s后执行doSomething
[self performSelector:@selector(doSomething:) withObject:nil afterDelay:3.0];
[[NSRunLoop currentRunLoop] run];//此处需要添加到Runloop,子线程默认没有开启,后期文章会具体说明
}
- (void)doSomething:(id)obj {
NSLog(@"完成了当前的任务!%@", [NSThread currentThread]);
[self completed];
}
- (void)completed {
@synchronized (self) {
self.executing = NO;
self.finished = YES;
}
}
- (void)cancel {
[super cancel];
if (self.isStart) {
[self completed];
}
}
@end
@implementation CustomOperation
@synthesize finished = _finished, executing = _executing;
- (BOOL)isAsynchronous {
return NO;
}
- (void)setFinished:(BOOL)finished {
[self willChangeValueForKey:@"finished"];
_finished = finished;
[self didChangeValueForKey:@"finished"];
}
- (void)setExecuting:(BOOL)executing {
[self willChangeValueForKey:@"executing"];
_executing = executing;
[self didChangeValueForKey:@"executing"];
}
- (void)start {
@synchronized (self) {
self.start = YES;
if (self.isCancelled) {
[self completed];
return;
}
@autoreleasepool {
[self main];
}
self.executing = YES;
}
}
- (void)main {//在此处做一些更复杂的操作
NSLog(@"准备开始执行任务啦~ %@", [NSThread currentThread]);
//模拟3s后执行doSomething
[self performSelector:@selector(doSomething:) withObject:nil afterDelay:3.0];
[[NSRunLoop currentRunLoop] run];//此处需要添加到Runloop,子线程默认没有开启,后期文章会具体说明
}
- (void)doSomething:(id)obj {
NSLog(@"完成了当前的任务!%@", [NSThread currentThread]);
[self completed];
}
- (void)completed {
@synchronized (self) {
self.executing = NO;
self.finished = YES;
}
}
- (void)cancel {
[super cancel];
if (self.isStart) {
[self completed];
}
}
@end
运行结果:
准备开始执行任务啦~ <NSThread: 0x600000b58380>{number = 8, name = (null)}
完成了当前的任务!<NSThread: 0x600000b58380>{number = 8, name = (null)}