[英]Objective-C passing a block into a block
這是一個棘手的情況。 我一直在研究塊,並且是第一次開始實現它們,而我發現自己想創建一個“復合塊”。 這大概是我的代碼:
- (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,所以我在塊內明確聲明了一個(block)變量,並為其分配了變量以嘗試使其保留(也許有點愚蠢,但我在ARC下運行,因此無法進行手動保留調用)。
無論如何,顯然,compoundBlock在傳遞給UIView時會被保留,但是由於我在ARC下運行,因此我不確定如何將我的onCompletion / innerCompletionBlock保留在compoundBlock中。
提前致謝 :)
啊哈,想通了。 有點愚蠢,真的。
在有些情況下我打電話的方法不同的時間- (void)moveToPosition:...
並通過nil
到completionBlock
參數......因為我並不需要在動畫的最后做任何額外的東西,只希望[self unlockInteractionFromPullDownMenuTab];
這是在compoundBlock中添加的。
有道理吧?
...僅在調用該塊之前檢查是否為零。 如SO上其他地方所討論的,“執行塊時,首先測試塊是否為零很重要”。 好吧,我在那里學到了教訓。
此代碼有效:
// Compound completion block
void (^compoundBlock) (BOOL completed) = ^(BOOL completed) {
[self unlockInteractionFromPullDownMenuTab];
if (completionBlock != nil) {
completionBlock(completed);
}
};
在堆棧上創建塊。 您需要將completionBlock
復制到堆中,以便可以確保在嘗試運行它時它仍然有效。 只需將其放在您的方法的頂部:
completionBlock = [completionBlock copy];
請注意,如果completionBlock
已在堆上,則只會返回相同的堆副本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.