0

我在我的應用程序中使用遊戲中心,我發現gamecentermanager.m文件會導致內存泄漏:爲什麼GameCenterManager.m中有內存泄漏?

- (void) callDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err 
{ 
assert([NSThread isMainThread]); 
if([delegate respondsToSelector: selector]) 
{ 
    if(arg != NULL) 
    { 
     [delegate performSelector: selector withObject: arg withObject: err]; 
    } 
    else 
    { 
     [delegate performSelector: selector withObject: err]; 
    } 
} 
else 
{ 
    NSLog(@"Missed Method"); 
} 
} 

泄漏發生(根據編譯器警告三角形),因爲performSelector(兩者的他們)選擇器是未知的。有兩件事我想知道

1)我直接從蘋果網站上的例子複製這個,所以如果蘋果建立它的代碼不會出現錯誤?

2)我該如何解決這個問題?作爲FYI,我使用的是使用LLMV編譯器3.1和標準(armv7)體系結構的Xcode 4.3.1。我也在使用ARC。

如果您需要任何其他信息,請讓我知道並感謝您的高級。

回答

1

這裏的問題是ARC不能告訴你用-performSelector:withObject:調用的方法的內存管理語義是什麼。在MRR下,這並不重要,因爲調用代碼需要相應地處理它(例如,如果它是一個擁有對象,則釋放返回值)。但是在ARC下編譯器需要才能知道這個信息是正確的。我不記得-performSelector:withObject:的默認行爲是什麼,它可能只是將它視爲非擁有的參考,在這種情況下,您並未實際泄漏。

處理這類代理模式的最簡單方法是仍然使用-respondsToSelector:,但是直接調用該方法,例如,

if ([_delegate respondsToSelector:@selector(foo:)]) { 
    [_delegate foo:self]; 
} 

在你的情況下,該方法本身並不知道選擇器是什麼。你最好的選擇可能是完全拋棄這種方法,並讓它的前呼叫者處理與代表交談。

+0

將不可能添加一個「假」類別NSObject聲明此方法?只是爲了「拼出」語義...... – nielsbot 2012-03-20 01:23:38

+0

@nielsbot:問題不在於缺少方法的聲明。問題是編譯器甚至不知道他試圖調用什麼方法,無論聲明如何,因爲他使用動態選擇器來調用它。 – 2012-03-20 02:33:02

+0

當然你是對的。沒關係。 – nielsbot 2012-03-20 07:20:50