NSMutableArray *groups = [NSMutableArray arrayWithArray:@[@"group1", @"group2", @"group3", @"group4"];
__block CommunicationCompletionHandler completion = [^{
[groups removeObjectAtIndex:0];
if ([groups count] > 0) {
// This will send some information to the network, and calls the completion handler when it receives a response
[mySocket saveGroup:groups[0] completion:completion];
}
} copy]; // Removing copy here doesn't work either
[mySocket saveGroup:groups[0] completion:completion];
在saveGroup:completion:
方法,我完成處理器添加到一個數組:
self.completionHandlers[SaveGroupCompletionHandlerKey] = [completion copy];
當我收到回覆,我撥打以下方法(key
在這種情況下爲SaveGroupCompletionHandlerKey
):
- (void)performCompletionHandlerForKey:(NSString *)key {
if (self.completionHandlers[key]) {
((CommunicationCompletionHandler)self.completionHandlers[key])();
[self.completionHandlers removeObjectForKey:key];
}
}
問題是完成處理程序只被調用一次。 removeObjectForKey:
行使塊解除分配。如果我取消註釋該行,一切工作正常。我不確定數組是如何提供這個塊的最後一個參考的,因爲我添加了一個copy
(我相信它正在優化到retain
)。
爲了清楚起見,應用程序的流程爲:通過網絡
- 發送數據,接收響應
- 呼叫完成處理程序
- 在完成處理程序,發送數據爲下一個組(這是遞歸部分)。
這裏有誰能指出我做錯了什麼?
無關,謝謝你的回答!你是對的,解決了這個問題。你能否再詳細說明爲什麼強/弱建議是錯誤的?塊不會簡單地超出範圍(在你的例子中)'foo'等於'NO'? –
@Scott:在非ARC代碼中,您可以對該塊進行復制,然後在遞歸完成後釋放該塊。 ARC負責爲您服務,除了它不知道遞歸何時結束並且沒有地方插入-release。因此你有一個沒有釋放的拷貝和一個泄漏。 (如果ARC在執行結束時簡單地釋放該塊,則連續調用該塊兩次將導致過度釋放)。一種解決方法是在遞歸完成後手動將塊變量設置爲零。這迫使ARC在正確的位置插入-release,但是這種方法很容易出錯。 – Darren
這很有道理,謝謝。 –