对于NSOperation
.如果要自定义的话,我们需要重写Start
或者main
.
对于start方法
If you are implementing a concurrent operation, you must override this method and use it to initiate your operation. Your custom implementation must not call super at any time.
对于main方法
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.
就是说如果咱们自定义的是并发的NSOperation
.那么我们得重写start
方法.如果是串行的话就需要重写main
方法.
AFNetWorking的例子
我们知道在AFN3.0
以上AFN完全替换成了NSURLSession.在3.0以下全都使用NSURLConnection
.在3.0以下用的是自定义的NSOperation.3.0以上用的是系统提供的.
图片一(AFURLConnectionOperation结构)
我们可以看出来.这个自定义NSOperation
没有重写main
方法.并且使用了NSRecursiveLock(递归锁)
来执行锁定、解锁操作
递归锁拓展
NSRecursiveLock(递归锁)
的好处是可以多次加锁不会造成崩溃.只有lock
和unlock
平衡了之后锁定的资源才会被释放.
可以看得出来AFNetworking子类化的AFURLConnectionOperation
是并发的.
图片二(AFURLConnectionOperation在NSOperation分类的结构).
看得出来.NSOperation的状态都重新实现了
2.串行操作
必须复写- (void)main;
方法
示例:
// MARK: CHOperationSERIAL.h
typedef NS_ENUM(NSUInteger, CHOperationSERIALState) {
CHOperationSERIALStateUnknow,
CHOperationSERIALStateReadyToStart,
CHOperationSERIALStateFinish,
};
@interface CHOperationSERIAL : NSOperation
@property (nonatomic ,assign) CHOperationSERIALState state;
@property (nonatomic ,assign) NSInteger count;
@end
// MAKR: CHOperationSERIAL.m
@interface CHOperationSERIAL ()
@property (nonatomic ,strong) NSRecursiveLock *lock;
@end
@implementation CHOperationSERIAL
- (NSRecursiveLock *)lock {
if (!_lock) {
_lock = [[NSRecursiveLock alloc] init];
}
return _lock;
}
- (void)main {
[self.lock lock];
if (self.isCancelled) {
[self operationDidCancel];
} else if (self.isReady) {
[self operationDidStart];
}
[self.lock unlock];
}
- (void)operationDidCancel {
NSLog(@"count:%ld func:%s", self.count ,__FUNCTION__);
}
- (void)operationDidStart {
NSLog(@"start: count:%ld %@", self.count ,[NSThread currentThread]);
[NSThread sleepForTimeInterval:arc4random_uniform(10)];
NSLog(@"end: count:%ld %@", self.count ,[NSThread currentThread]);
self.state = CHOperationSERIALStateFinish;
}
注意:使用的时候NSOperationQueue的最大并发数(maxConcurrentOperationCount)要设置为1
3. 并行操作
并行操作需要重写下面四个方法.
start
asynchronous (这个需要返回YES)
executing // 执行
finished // 完成(不返回YES就不会dealloc)
/// CHOperation.h
typedef NS_ENUM(NSUInteger, CHOperationState) {
CHOperationStateUnknow,
CHOperationStateReadyToStart,
CHOperationStateFinish,
};
NS_ASSUME_NONNULL_BEGIN
@interface CHOperation : NSOperation
@property (nonatomic ,assign) CHOperationState state;
@property (nonatomic ,assign) NSInteger count;
@end
// MARK: CHOperation.m
#import "CHOperation.h"
@interface CHOperation ()
@property (nonatomic ,strong) NSRecursiveLock *lock;
@end
@implementation CHOperation
- (NSRecursiveLock *)lock {
if (!_lock) {
_lock = [[NSRecursiveLock alloc] init];
}
return _lock;
}
- (void)start {
[self.lock lock];
if (self.isCancelled) {
[self operationDidCancel];
} else if (self.isReady) {
[self operationDidStart];
}
[self.lock unlock];
}
- (void)operationDidCancel {
NSLog(@"count:%ld func:%s", self.count ,__FUNCTION__);
}
- (void)operationDidStart {
NSLog(@"count:%ld func:%s", self.count ,__FUNCTION__);
self.state = CHOperationStateFinish;
}
- (BOOL)isFinished {
return self.state == CHOperationStateFinish;
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isAsynchronous {
return YES;
}
- (void)dealloc {
}
PS:有点偷懒,所以没写其余的状态.怎么写可以参考一下AFN3.0以下的自定义NSOperation.
AFN的例子是不管取消请求还是请求成功都算成了finish
.按照AFN的讲就是如果执行完操作不是finish
状态的话.NSOperation实例就不会销毁(不走dealloc).这点需要注意.