2012-10-07 46 views
2

這是一個棘手的場景。我一直在研究塊,並開始實施它們,我發現自己想要創建一個「複合塊」。這裏是我的代碼,大致爲:Objective-C將塊傳遞給塊

- (void)moveToPosition:(NSInteger)pos withVelocity:(CGFloat)vel onCompletion:(void(^)(BOOL completed))completionBlock 
{ 

    void (^compoundBlock) (BOOL completed) = ^(BOOL completed) { 
     [self unlockInteractionFromPullDownMenuTab]; 
     void(^innerCompletionBlock)(BOOL completed) = completionBlock; 
     innerCompletionBlock(completed); 
    }; 

    // Animate 
    [UIView animateWithDuration: duration 
        animations: ^void{ [self.pullDownMenu setFrame:newFrame]; } 
        completion: compoundBlock 
    ]; 


} 

的目標是採取傳入該方法的代碼塊,添加的東西給它,然後把它傳遞到動畫的方法調用。不過,我得到就行了不好的訪問:

innerCompletionBlock(completed); 

我的身影,我的innerCompletionBlock是越來越釋放,但我不完全知道爲什麼。根據我的理解,塊會複製你扔向他們的所有東西,包括引用自我 - 這可以創建保留週期,以及我最近學會避免的東西。

其實,我本來想這:

void (^compoundBlock) (BOOL completed) = ^(BOOL completed) { 
    [self unlockInteractionFromPullDownMenuTab]; 
    completionBlock(completed); 
}; 

但我是越來越壞訪問,和我猜想,也許compoundBlock沒有複製completionBlock,所以我明確聲明內(塊)變量該塊並分配它試圖讓它保留(也許有點愚蠢,但我在ARC下運行,所以我不能做手動保留調用)。無論如何,顯然compoundBlock在傳遞給UIView時被保留,但我不確定如何在複合塊內保留我的onCompletion/innerCompletionBlock,因爲我在ARC下運行。

在此先感謝:)

回答

1

啊哈,算出來了。有點愚蠢,真的。

有我在那裏調用方法- (void)moveToPosition:...並傳遞nilcompletionBlock參數......因爲我並不需要在動畫的最後做任何額外的東西,只希望這是上漲的[self unlockInteractionFromPullDownMenuTab];不同時間在複合塊中。

有意義吧?

...只有在您調用該塊之前檢查零,正如SO上的elsewhere所討論的那樣,「當你執行一個塊時,首先測試該塊是否爲零是很重要的」。那麼,我在那裏吸取了教訓。

此代碼:

// Compound completion block 
void (^compoundBlock) (BOOL completed) = ^(BOOL completed) { 
    [self unlockInteractionFromPullDownMenuTab]; 
    if (completionBlock != nil) { 
     completionBlock(completed); 
    } 
}; 
0

在堆棧上創建塊。您需要將completionBlock複製到堆中,以便確保它在嘗試運行時仍然有效。只要把這個在你的方法頂部:

completionBlock = [completionBlock copy]; 

注意,如果completionBlock已經堆上,這只是返回同一個堆副本。

+0

唔...我很欣賞你快速的答案。我有一個問題:在ARC下複製一個仍然需要的塊? (看起來不是。)爲了論證,如果在ARC下運行*不*運行,我將如何去調用上面示例中的兩個塊的副本?只需在該方法頂部的'completionBlock'處添加一次,而不添加到'compoundBlock',因爲它本身將由UIView動畫調用內部複製?謝謝。 –

+0

如果不是在ARC下,每個'copy'必須通過'release'或'autorelease'進行平衡。在很多情況下,沒有必要在ARC下複製塊,但仍然有必要的情況下,所以我傾向於預防性地進行。 –

+1

這不是真的。他不需要在給定的例子中在MRC或ARC中明確地複製'completionBlock'塊。該方法不會存儲'completionBlock',以便以後在任何地方使用,除非被另一個塊'compoundBlock'捕獲。當(和如果)'compoundBlock'被複制時,它會自動複製'completionBlock'。 – newacct