2014-03-19 38 views
6

當我有一個目標C實例創建需要參照實例的塊,我經常通過一個弱指針,不會使實例保持活躍,併產生一個保留循環,這樣做:成語隱藏目標C塊中的「自我」?

__weak MyType *const weakSelf = self; 
void (^aBlock)() = ^(){ 
    // Do things with weakSelf instead of self. 
} 

我想要一個能夠阻止我利用塊中強壯自我的成語。理想情況下,如果我在塊中使用self而不是weakSelf,那麼在使用習慣用法時,會出現編譯錯誤。運行時錯誤也可以。

+3

你可以得到一個警告..會有幫助嗎? –

+2

最新版本的Xcode + ARC將以塊爲單位檢測強參考週期並給出警告。 –

+0

警告很有幫助,謝謝。我有一個解決方案,我會發布。這並不完美,但它可能會引發更好的解決方案。 – Benjohn

回答

1

我有一個解決方案,我不特別喜歡,但它可能會引發更好的答案。我會留下這個未解決的問題,希望能有更好的解決方案。

下面是做這件事:

// Here's a method definition… 
-(void) aMethod 
{ 
    // Want to create a block in which its impossible to refer to strong "self". 
    // Begin a new scope to do this in. 
    { 
    // Within this scope, cover the existing "self" with a weak variant. 
    __weak STWeatherTableViewController const *weakSelf = self; 
    __weak STWeatherTableViewController const *self = weakSelf; 

    // Sadly it's _not_ possible to simply do: 
    // __weak STWeatherTableViewController const *self = self; 
    // … it gives a warning about initialisation of a variable form its own 
    // uninitialised value, which makes sense, though you might hope the 
    // compiler would work out what's going on. 

    // Make a block that captures the covered self and does something with it. 
    void (^exampleBlock)() = ^(){ [self lineHeight]; }; 
    exampleBlock(); 
    } 

    // Now, back in the scope of the original method, "self" is non weak 
    // again. 
    [self doSomething]; 
} 

我想,如果你真的關心了很多關於這一點,你可以使用宏。這將至少抽象的想法,並使用很容易找到,在代碼中聲明:

#define WEAKEN_SELF(classType) \ 
__weak classType const *weakSelf = self; \ 
__weak classType const *self = weakSelf 

甚至:

#define WEAKEN_SELF(classType) \ 
__weak classType const *weakSelfTemporary##__LINE__ = self; __weak classType const *self = weakSelfTemporary##__LINE__; 

,你會使用這樣的:

-(void) testMethod 
{ 
    // You still need that scope or you cover the original "self". 
    { 
    WEAKEN_SELF(STWeatherTableViewController) 
    void (^exampleBlock)() = ^(){ [self someMethodOrOther]; }; 
    exampleBlock(); 
    } 
} 

雖然我不相信這是值得的。編譯器警告可能已經足夠好了,他們可能會被誤解爲錯誤?

+0

有趣的解決方案:) –