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