2011-12-02 50 views
9

好了,我明白如何避免self保持與塊週期,怎麼樣的情況下,當我發送消息到自由的方法在調用堆棧嵌套更深這樣的塊中:塊和從調用的方法自

- (void)methodA { 
    __block MyClass *blockSelf = self; 
    [someObject block:^{ 
     [blockSelf methodB]; 
    }]; 
} 

- (void)methodB { 
    ... 
    [self methodC]; 
    ... 
} 

- (void)methodC { 
} 

在這種情況下[blockSelf methodB]是好的,但發送[self methodC]methodB導致保留週期與否?在任何地方找不到答案...

回答

8

那裏沒有保留週期。當在方法內定義塊字面值時,塊可以捕獲的上下文僅限於該方法內可見的內容在您的例子:

- (void)methodA { 
    __block MyClass *blockSelf = self; 
    [someObject block:^{ 
     [blockSelf methodB]; 
    }]; 
} 

塊文字,即:

^{ 
    [blockSelf methodB]; 
} 

能夠看到以下內容:

  1. self_cmd,這是隱藏在每一個目標可用參數-C方法。如果-methodA有形式參數,Block字面也可以看到它們;
  2. 函數/方法塊內的任何塊變量變量,即方法內的每個局部變量,以及在定義塊文字的位置都可見的變量。在這個例子中,-methodA中唯一的局部變量是blockSelf,因爲它的__block合格,所以不保留;
  3. 任何文件範圍變量(又名全局變量)。

塊文字不知道(在一般情況下,不能意識到)其他函數/方法內發生的情況,因此無論在被調用的函數/方法中可用的上下文都不會被塊文字捕獲。您只需要擔心定義塊字面值的方法。

參照封鎖/ lambda表達式(即,^{})和小寫字母塊參照至C塊時,當我使用大寫塊的蘋果公司的約定(亦即,{})。

+0

很酷,謝謝!這將從我的幫手方法中刪除一堆醜陋的「參數攻擊」...... – Tom

+0

「這裏沒有保留週期。」那麼這取決於someObject是什麼,以及它是否保留傳遞給它的塊。如果'self'保留了'someObject'(比如它是一個實例變量),並且'someObject'存儲並保留了傳遞給'block:'的塊,那麼就會有一個保留週期。 – newacct