2012-09-10 58 views
3

在沒有塊創建強引用(並因此增加引用計數)的塊內引用「自我」(和ivars)的正確方法是什麼?參照自身和實例變量的塊

例如,我發現下面的遞增引用計數爲「自我」:

^(id sender) { 
    [self.navigationController popViewControllerAnimated:YES]; 
} 

爲了避免上述情況,我一直在做以下操作:

__weak WhateverController *weakSelf = self; 
^(id sender) { 
    [weakSelf.navigationController popViewControllerAnimated:YES]; 
}; 

是的,我意識到這是僞代碼。

回答

10

此外,間接引用自還創建了一個保留自我。例如,如果_ivar是一個實例變量,則訪問它是對自我的隱式引用,因此以下內容也將保留自己。

^(id sender) { 
    [_ivar popViewControllerAnimated:YES]; 
} 

此外,在您的weak例如擴大,它是確定將消息發送到弱引用。如果它是零,什麼都不會發生。如果不是,那麼編譯器將生成代碼,通過調用方法確保引用保持有效。

所以,這是罰款:

__weak Foo *weakSelf = self; 
^(id sender) { 
    [weakSelf.foo doSomething]; 
} 

因爲富要麼是nil如果還是不行,可以保證它始終保持的doSomething執行非空。

然而,以下是不明智的,因爲self可以去nil在兩者之間通話,這可能不是你想要什麼:

__weak Foo *weakSelf = self; 
^(id sender) { 
    [weakSelf.foo doSomething]; 
    [weakSelf.foo doSomethingElse]; 
} 

在這種情況下,你可能想創建自己的很強的借鑑意義在塊內部,所以在塊的執行過程中你有一個一致的值。

在另一方面,如果直接通過弱引用訪問實例變量,你必須弱強的舞蹈,因爲這樣的代碼:

__weak Foo *weakSelf = self; 
^(id sender) { 
    weakSelf->_foo = bar; 
} 

將炸燬如果weakSelfnil

因此,在上述最後兩種情況,你想要做的事,如:

__weak Foo *weakSelf = self; 
^(id sender) { 
    Foo *strongSelf = weakSelf; 
    if (!strongSelf) return; 
    // Now, do anything with strongSelf, as it is guaranteed to be around 
} 

當然,伊娃的情況是隻有一個問題,如果你真正直接訪問高德...

+1

在你的第二個例子,我認爲你的意思是'[weakSelf.foo doSomething]; [weakSelf.foo doSomethingElse];' –

+0

@ChristopherPickslay - 的確如此。謝謝! –

2

蘋果的記譜法是自己的,但除此之外 - 你很好。
在非圓弧項目中使用以下代碼來防止「自我」從由塊被保留:
__block id sself = self