建立一個支援非同步作業的operation,建立非同步operation

來源:互聯網
上載者:User

建立一個支援非同步作業的operation,建立非同步operation

NSOperationQueue時iOS中常用的任務調度機制。在建立一個複雜任務的時候,我們通常都需要編寫?NSOperation的子類。在大部分情況下,重寫main方法就可以滿足要求。main方法執行完畢後,系統就會認為這個operation完成了。

 

有時候情況並沒有這麼簡單。我們需要在operation中調用非同步API,這個API會通過一個block或者代理通知我們結果。這時只靠覆蓋main方法就顯得力不從心了。因為非同步API尚未執行完畢,operation就提前結束了。

 

怎麼解決這個問題呢?我想到AFNetworking中有同樣的案例,於是參考了其中的實現,設計了一個基於非同步任務的operation。

 

我們需要覆蓋start方法。這個方法的作用有點類似於main方法,在這裡實現任務的代碼邏輯。系統怎麼知道我們的任務開始執行,或者完成了呢?系統會通過KVO的形式,監聽operation的一些屬性。我們可以重新實現這些屬性,來通知系統任務執行的狀態。重要的屬性有:

@property (readonly, getter=isReady) BOOL ready;@property (readonly, getter=isExecuting) BOOL executing;@property (readonly, getter=isFinished) BOOL finished;

 

它們都是唯讀屬性。我們可以簡單的重寫它們,返回我們想要的值。但是如何通知系統它們的值已經變化了呢?如果你瞭解KVO,那麼你就應該知道NSObject的這一對方法能夠協助我們,可以利用它們手動通知系統某個屬性發生了變化。

- (void)willChangeValueForKey:(NSString *)key;- (void)didChangeValueForKey:(NSString *)key;

 

下面就是完整的代碼。這裡只用了一個NSTimer類比一個非同步任務。在state變化時,我們需要通知KVO系統operation的狀態發生了變化。這一步很重要,我剛開始忽略了手動通知KVO,導致任務永遠無法完成(即使start中的任務全部執行完畢)。

typedef NS_ENUM(NSInteger, MyOperationState) {    MyOperationStateReady,    MyOperationStateExecuting,    MyOperationStateFinished};@interface MyOperation : NSOperation@property (nonatomic, strong) NSTimer *exeTimer;@property (nonatomic, assign) MyOperationState state;@property (nonatomic, strong) NSLock *lock;@end@implementation MyOperation- (instancetype)init{    self = [super init];    if (self) {        self.lock = [NSLock new];        [self willChangeValueForKey:@"isReady"];        self.state = MyOperationStateReady;        [self willChangeValueForKey:@"isReady"];    }    return self;}- (void)start{    [self.lock lock];    if (!self.finished && self.state == MyOperationStateReady) {        [self willChangeValueForKey:@"isExecuting"];        self.state = MyOperationStateExecuting;        [self didChangeValueForKey:@"isExecuting"];        self.exeTimer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(finish) userInfo:nil repeats:NO];        [[NSRunLoop mainRunLoop] addTimer:self.exeTimer forMode:NSRunLoopCommonModes];    }    [self.lock unlock];}- (void)cancel{    [self.lock lock];    if (!self.isFinished && !self.cancelled) {        [super cancel];        [self.exeTimer invalidate];    }    [self.lock unlock];}- (BOOL)isReady{    return self.state == MyOperationStateReady;}- (BOOL)isExecuting{    return self.state == MyOperationStateExecuting;}- (BOOL)isFinished{    return self.state == MyOperationStateFinished;}- (BOOL)isAsynchronous{    return YES;}- (BOOL)isConcurrent{    return YES;}- (void)finish{    [self.lock lock];    [self willChangeValueForKey:@"isFinished"];    self.state = MyOperationStateFinished;    [self didChangeValueForKey:@"isFinished"];    [self.lock unlock];}@end

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.