4

我熟悉委託模式和nilling我的委託,特別是當我的視圖控制器消失時仍在進行異步調用。我沒有委託,回調成功返回一個零對象。保護我的代碼免於殭屍從完成塊

我現在正在嘗試使用完成塊來使我的代碼更容易閱讀。

我從我的視圖控制器調用網絡服務,並通過一個塊更新我的UITableView。在正常情況下,它工作正常。但是,如果我在視圖完成之前離開視圖,則會執行完成處理程序塊 - 但UITableView現在是一個殭屍。

最常見的處理方式是什麼?

WITH代碼示例

這是iPad程序UPDATE,我有個屏幕視圖控制器一次,像一個拆分視圖。一個是細節,另一個是圖像網格。我點擊一個圖像,它告訴詳細信息加載信息。但是,如果在他們有機會進行網絡通話之前點擊圖像速度太快 - 我遇到問題。在不斷變化的圖片下面的代碼被稱爲其計數圖像的最愛....

因此,這裏是我的困境,如果我用下面的代碼 - 它工作正常,但它在工具,如果你之前的切換圖像泄露網絡響應。

如果我刪除__block並自己傳入,那麼它會與殭屍崩潰。

我不能贏......我確定我錯過了關於使用塊的基本知識。

__block UITableView *theTable = [self.table retain]; 
__block IndexedDictionary *tableData = [self.descriptionKeyValues retain]; 
FavouritesController *favourites = [Container controllerWithClass:FavouritesController.class]; 
[favourites countFavouritesForPhoto:self.photo 
         completion:^(int favesCount) { 

          [tableData insertObject:[NSString stringWithFormat:@"%i", favesCount] 
               forKey:@"Favourites:" atIndex:1];     
          [theTable reloadData]; 

          [tableData release]; 
          [theTable release]; 
         }]; 

任何提示?由於

第二次更新

我改變了我加載的最愛的方式。而不是最喜歡的單身人士,我在每次更改照片時創建一個實例。通過更換這並殺害舊 - 塊無處可回調(我猜它甚至不存在)和我的代碼現在看起來就像下面的,它似乎工作:

[self.favourites countFavouritesForPhoto:self.photo 
         completion:^(int favesCount) {  
          [self.descriptionKeyValues insertObject:[NSString stringWithFormat:@"%i", favesCount] 
               forKey:@"Favourites:" atIndex:1];     
          [self.table reloadData]; 
         }]; 

它不會泄漏,也不會崩潰。

+0

'retain' +'release'?但我不確定保證完成塊將被執行 – Nekto 2012-02-18 13:54:21

+0

在這種情況下,我認爲你是對的。我回到塊編程指南,並重新閱讀,「標記爲__block存儲類型修飾符的對象變量,但不保留」....我正在做。但是,這是因爲我的視圖控制器還在那裏...如果不是?或者它總是在那裏,因爲該塊保持活着?啊腦頭疼...... – bandejapaisa 2012-02-18 14:02:38

+2

+1爲'保護我的代碼從殭屍';-) – 2012-02-18 14:37:27

回答

0

我建議你測試tableview不是在塊的開始零。這聽起來像是當它的父視圖離開屏幕時正確丟棄tableview,所以在那之後,沒有任何tableview操作是有效的。

保留塊內的UITableView的是一個壞主意,因爲數據源/ tableview中的更新可能會導致隱式方法調用和通知,如果實現代碼如下是不是在屏幕上,這將是不相關的。

+0

如果我將視圖控制器推到導航堆棧上,我的tableview將不會爲零。我將會彙集另一個示例項目來測試這一點。謝謝 – bandejapaisa 2012-02-18 17:16:02

0

Block將保留它引用的任何對象,但那些使用__block註釋的對象除外。如果您不想執行完成塊,只需調用isCancelled之類的屬性,然後在調用完成塊之前檢查它是否爲YES

+0

是的,我讀到了關於__block vars的保留。被取消似乎是一個有趣的模式,但每當我看到布爾拋出時總會對我產生不好的影響。 – bandejapaisa 2012-02-18 17:14:23

+0

它被可可的NSOperation使用,所以我認爲它不壞。你的任務可以有不同的狀態。延遲,取消,進行中等等。這取決於你是否保持它。 – 2012-02-18 18:31:33

+0

我會看看,也許這是我必須去的方式。謝謝 – bandejapaisa 2012-02-19 21:04:51

0

所以,你必須擁有再打另一個對象它完成和對象可在此期間被摧毀後,後臺操作。當你有非保留的引用時,你描述的崩潰發生。你看到的問題是被引用的對象消失,指針無效。通常情況下,你要做的就是取消註冊dealloc方法裏面的代表,這樣的後臺任務仍在繼續,每當它準備將結果傳送回它說:「拍攝,我的回調對象是零」,至少它不」 t崩潰。

但是,處理手動弱引用是單調乏味且容易出錯的。您可以忘記在dealloc方法內部委託一個委託,並且在您遇到代碼崩潰的情況之前,它可能會在幾個月內無需通知。

如果你的目標的iOS 5.0我會在ARC,它提供了弱引用讀了。如果您不想使用ARC,或者需要定位5.x之前的設備,那麼我會建議使用調零等弱參考庫,如MAZeroingWeakRef,它們也適用於3.x設備。

無論使用哪種ARC的弱引用或MAZeroingWeakRef,你將與指向回到你的表這些花哨弱引用對象的一個​​實現後臺任務。現在,如果指向的對象消失,弱指針將自行刪除,並且後臺任務不會崩潰。

+0

感謝您的回覆,但您已經稍微離開了話題。我對此並不陌生。我知道如何使用代表,我不使用ARC。我的問題是有關異步塊完成處理程序的模式。然而,關於你的答案 - 我會忽略我的代表viewWillDisappear,而不是dealloc方法,這可能太遲了 - 你只需要在慢速連接上使用你的應用程序,或者使用網絡優化器來減慢你的模擬器網絡,而你可以在數秒內顯示潛在的委託回調,而不是幾個月。 – bandejapaisa 2012-02-18 17:12:51

+0

您問「處理這個問題的常用模式是什麼」,我回答:無回調或使用清零弱引用。什麼是主題?這是我目前用於處理異步塊完成處理程序的編程模式。另外,如果你在viewWillDisappear中爲零,那麼爲時過早,因爲如果在此期間任務完成時呈現模態視圖控制器,則不會收到回調。 – 2012-02-18 18:50:52

+0

也許脫離主題是錯誤的短語......但你引用了代表模式,我說我知道並使用它。根據我的經驗,在dealloc中扼殺代表已經太晚了。我想這取決於用例,但是對於模態viewWillDisappear聽起來太早了。感謝弱指針信息。 – bandejapaisa 2012-02-19 21:04:14