2

我創建了一個NSOperation,其目標是從20個URL下載幾張圖片(如20)。 因此,在此NSOperation中,我創建了20 AFImageRequestOperation將它們添加到NSOperationQueue並在隊列上調用-waitUntilAllOperationsAreFinishedNSOperationQueue INSIDE an NSOperation

問題是,它不會等待,它立即返回。下面是代碼

- (void)main { 
    NSArray *array = [I have the 20 links stored in this array]; 

    self.queue = [[NSOperationQueue alloc]init]; 
    self.queue.maxConcurrentOperationCount = 1; 

    for (int i = 0; i < array.count; i++) {     
     NSURL *url = [NSURL URLWithString:[array objectAtIndex:i]]; 
     NSURLRequest *request = [NSURLRequest requestWithURL:url]; 

     AFImageRequestOperation *op = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) { 
      return image; 
     } success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 
     // SUCCESS BLOCK (not relevant) 
     } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { 
     // FAILURE BLOCK (not relevant) 
     }]; 

     [self.queue addOperation:op]; 
    } 

    [self.queue waitUntilAllOperationsAreFinished]; // Here is the problem it doesn't wait 
    DDLogWarn(@"-- %@ FINISHED --", self); 

} 

在控制檯中,DDLogWarn(@"-- %@ FINISHED --", self);打印每一個業務甚至開始之前,所以我的猜測是,waitUntilAllOperationsAreFinished沒有做好自己的工作,並沒有等待,而是20個行動仍在運行之後這可能意味着main還沒有返回,所以我不知道該怎麼想。

編輯1:其實我很想知道,如果我的DDLog裏面的成功和失敗塊,因爲waitUntilAllOperationsAreFinished是阻塞線程,直到所有的操作完成。這也許可以解釋爲什麼我沒有看到任何事情突然發生。

回答

5

我認爲它是有用創建一個包含其他NSOperations出於同樣的原因給你,即我有很多的小任務組成的NSOperation一個更大的任務,我想把更大的任務作爲一個單元來處理,並在完成時告知它。我還需要序列化更大任務的運行,因此一次只能運行一個任務,但是當每個大任務運行時,它可以在其中執行多個併發操作。

在我看來,和你一樣,創建一個NSOperation來管理這個大任務是一個很好的方法,另外我還沒有閱讀文檔中的任何內容,說沒有這樣做。

它看起來像你的代碼可能畢竟工作,所以你可以繼續使用NSOperation。

根據您的情況阻塞線程可能是合理的。如果阻塞是不是合理的,但你想繼續使用的NSOperation你需要創建一個「並行」 NSOperation看到Concurrency Programming Guide: Configuring Operations for Concurrent Execution

如果只允許一個圖像下載的時間,你可以使用@jackslashs建議,在信號操作結束,或者如果您想允許併發映像下載,則可以使用單個NSBlockOperation作爲最終操作,並使用-[NSOperation addDependency:]使其依賴所有其他操作,以便最後運行。

當您收到所有信息都已完成的信號並且您可以按照文檔中所述正確設置isFinishedisExecuting標記以完成主要的NSOperation

無可否認,這具有一定程度的複雜性,但您可能會覺得它很有用,因爲一旦將複雜性隱藏在NSOperation之內,外部代碼可能會更簡單,就像我一樣。

如果您決定創建Concurrent NSOperation,您可能會發現蘋果示例代碼LinkedImageFetcherQRunLoopOperation作爲一個起點。

+0

這正是我所需要的,爲自己設置'isFinished'和'isExecuting'標誌。它完美的作品非常感謝你:) – ItsASecret 2013-02-13 15:40:44

1

此代碼不需要位於NSOperation之內。相反,使類,也許是一個單身,有一個操作隊列,使一種稱爲

-(void)getImagesFromArray:(NSArray *)array 

或類似的東西以上代碼將正常工作入列到這個隊列。您無需致電waitUntilAllOperationsAreFinished。這是一個阻塞的電話。如果您的隊列的最大操作數爲1,則只需在添加完所有網絡操作後再添加其他操作,然後在執行時知道所有其他操作已完成。你可以只添加一個簡單的塊操作結束:

//add all the network operations in a loop 
[self.operationQueue addOperation:[NSBlockOperation blockOperationWithBlock:^{ 
    //this is the last operation in the queue. Therefore all other network operations have finished 
}]]; 
+0

好的我應該多說一句,這20張圖像就像是一本書或專輯中的一首歌,或者我不知道,但是我要將這些操作排入大量的應該下載20個左右的項目,這就是爲什麼我想製作NSOperation – ItsASecret 2013-02-12 12:59:48

+0

也許我應該重新考慮整個事情,謝謝你花時間回答。 – ItsASecret 2013-02-12 13:23:45

+0

'AFImageRequestOperation'已經是'NSOperation'。你不需要自己做! – jackslash 2013-02-12 15:26:42

相關問題