2012-12-11 43 views
2

我有兩個不同類的實例,他們都需要將完成塊添加到特定操作。我會嘗試一般地解釋這個問題,而不是解釋我的應用程序正在嘗試做的所有事情。鏈接完成塊

視圖控制器正在調用資源管理器類的實例來保存資源。資源管理器然後調用要保存的資源的類以獲得保存的網絡操作。

的資源的實例創建操作,並賦予它一個完成塊,這將影響到資源的狀態時,它將觸發。

這是我的問題是 - 資源類還需要完成塊,以便增加該操作的視圖控制器的保存成功或失敗的通知。

下面是關於管理者的保存方法的SNIPPIT:

-(void)save:resource withCompletion:completion 
{ 
. 
. 
. 

NSOperation *operation = [resource operationForSave]; 

NSOperation __weak *weakOperation = operation; 
void(^__weak resourceCompletion)(void)= operation.completionBlock; 

[operation setCompletionBlock:^{ 
    if (resourceCompletion) { 
     resourceCompletion(); 
     } 

    if (completion) { 
     if (weakOperation.error) { 
      completion(NO, operation.error); 
      } 
     else { 
      completion(YES, nil); 
      } 
     } 
    }]; 

. 
. 
. 
// add the operation to a network operation queue 
} 

雖然我認爲這將在技術上的工作,我沒有瘋了。它感覺很時髦。我寧願有一個塊封裝第二個塊,但這是不可能的,因爲視圖控制器和資源正在創建他們自己的完成塊,並且管理員類是必須將它們粉碎在一起的那個塊。

有沒有更優雅的方式來鏈接這些兩個完成塊一起,在這種情況下,或者是我現在創建一個塊包含原始兩大塊最好的,我要得到的方法是什麼?

任何輸入將不勝感激。

+1

爲什麼你使用'__weak'呢? –

+0

你可能會從http://programmers.stackexchange.com得到更多的幫助,因爲這更像是一個設計問題而不是實際問題。你的方法雖然是健全的,但有時你只需要做這樣的事情。或者,您可以使用委託模式或通知或三者的任意組合。用於編程的萬歲。 – Bergasms

+0

我正在使用__weak來避免保留週期 - 完成塊捕獲操作,該操作對塊有很強的參考。 – alivingston

回答

1

的代碼你貼大概會工作。當您用自己的塊替換操作的完成塊時,可能會刪除對原始完成塊的唯一強引用(由資源設置)。所以你的resourceCompletion變量很弱,在setCompletionBlock:返回時將變爲零。

只是讓resourceCompletion強應該解決這個問題。但是,如果你想要做一個更清潔的方式,修改operationForSave消息(對資源)拍攝完成塊本身:

__block NSNetworkOperation *operation = [resource operationForSaveWithCompletion:^{ 
    NSError *error = operation.error; 
    completion(error == nil, error); 

    // Break the retain cycle between this block and the operation object. 
    operation = nil; 
}]; 

,使之成爲資源自身的內部完成塊的工作來調用完成塊你提供。

如果你不想或者不能修改資源的API,你仍然可以通過消除弱引用簡化代碼:

__block NSNetworkOperation *operation = [resource operationForSave]; 
__block void (^priorCompletion)(void) = operation.completionBlock; 
operation.completionBlock = ^{ 
    if (priorCompletion) { 
     priorCompletion); 
     // Break possible retain cycle. 
     priorCompletion = nil; 
    } 

    NSError *error = operation.error; 
    completion(error == nil, error); 
    // Break the retain cycle between this block and the operation object. 
    operation = nil; 
}; 

而且,我真誠地希望你真的沒有一個名爲NSNetworkOperation類,因爲Apple reserves the NS prefix (and all other two-letter prefixes) for its own use.

+0

這是一個錯字,它是一個NSOperation。 – alivingston

+0

感謝您的回覆。我使用弱引用來避免保留週期。我並沒有想過讓他們無法打破保留週期。 – alivingston