2016-03-25 31 views
0

我正在使用一個UIDocument子類,它有可能從多個線程中調用saveToURL方法。因此,我已包裹它,我想使線程安全的包裝功能:使用@synchronized與同步操作

- (void)saveWithCompletionBlock:(void(^)(TransactionDocumentReturnCode status))completion { 
    @synchronized (self) { 
     [self saveToURL:[self fileURL] forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success){ 
      // Generate returncode depending on outcome of save operation 
      completion(returncode); 
     }]; 
    } 
} 

我假設調用[self saveToURL:...]會立即返回,因爲本身發生在後臺線程保存操作,導致鎖在保存操作完成之前可能被釋放。那麼,有沒有辦法讓其他線程調用saveWithCompletionBlock:被阻止,直到saveToURL的完成塊被調用?

+0

看看這個答案有兩種實現方法:http://stackoverflow.com/a/7649768/78496 – chedabob

+0

謝謝@sedabob。使用GCD或NSOperationQueue會導致對保存包裝函數的後續調用被阻塞,直到保存操作的完成塊完成? – mashers

回答

0

我剛纔想到的一個潛在解決方案是向我的UIDocument子類中添加一個屬性,以指示是否正在執行保存操作,如果是,請等待,然後重試。結束語這個屬性的檢查和設置在@synchronize應防止兩個線程同時讀取的值設置爲false,並相信他們能夠保存文檔:

- (void)saveWithCompletionBlock:(void(^)(TransactionDocumentReturnCode status))completion { 
    @synchronized(self){ 
     if (self.isSaving) { 
      [self performSelector:@selector(saveWithCompletionBlock:) withObject:completion afterDelay:1.0]; 
      return; 
     } 

     self.isSaving = YES; 
    } 

    [self saveToURL:[self fileURL] forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success){ 
     // Generate returncode depending on outcome of save operation 
     completion(returncode); 
     self.isSaving = NO; 
    }]; 
} 

我不知道這是否會是足夠的,或者認爲是良好的多 - 線程練習。

+0

上述解決方案似乎運作良好。在[self performSelector:...]之前向'[NSObject cancelPreviousPerformRequestsWithTarget:self]'添加調用導致應用程序等待第一次保存操作結束,然後在完成後再次保存一次。我仍然歡迎有關此解決方案的任何反饋。 – mashers