2012-10-26 36 views
1

我正在使用一個庫,在後臺執行一些工作,然後調用完成處理程序。所有非常標準。取消完成處理程序塊運行

[[LastFm sharedInstance] getInfoForArtist:@"Pink Floyd" successHandler:^(NSDictionary *result) { 
    // Do stuff... 
} failureHandler:nil]; 

我實際上在tableview中使用這個:在每個單元格(子類)中,我得到關於藝術家的信息並顯示它。這也是問題:當單元格被移出屏幕並重新用於其他藝術家時,前一個藝術家的successHandler仍然可以執行,從而導致標籤和圖像快速連續多次更改。

我的想法是創建一個NSOperationQueue,加上其內部的getInfoForArtist電話,並確保它可以被取消:

NSBlockOperation *operation = [[NSBlockOperation alloc] init]; 
__weak NSBlockOperation *weakOperation = operation; 

[operation addExecutionBlock:^{ 
    [[LastFm sharedInstance] getInfoForArtist:mediaItem.artist successHandler:^(NSDictionary *result) { 
     if (weakOperation.isCancelled) { 
      return; 
     } 
     // Do stuff... 
    } failureHandler:nil]; 
}]; 

[self.queue addOperation:operation]; 

的問題是,weakOperation總是successHandler內空。如果我將其更改爲__block而不是__weak,則weakOperation是正確的實例,但其isCancelled狀態始終爲NO

我在正確的時間打電話給[self.queue cancelAllOperations];,當時單元格被移出屏幕。

所以我的問題是,如何防止在單元格被其他藝術家重用之後運行successHandler?

回答

2

問題是您正在調用異步API。您的操作的生命週期是致電getInfoForArtist:successHandler:,可能立即返回。在執行異步回調時,操作已被處理,這就是爲什麼引用在回調塊內部爲零的原因。

當執行successHandler時,取消操作沒有意義 - 您不會節省網絡資源,並且您也可以在本地保存查找結果。用戶界面的問題是,你不應該直接引用單元格(或其子視圖,如果你重用它們)。您可能會考慮將結果存儲在本地NSDictionary中,該NSDictionary鍵位於該行的NSIndexPath或藝術家ID。然後,在您的cellForRowAtIndexPath:中,首先在進行LastFM調用之前檢查該字典。在successHandler回調中,您可以遍歷tableView的visibleCells並嘗試從字典中加載數據。

相關問題