为什么GameCenterManager.m中有内存泄漏?
问题描述:
我在我的应用程序中使用游戏中心,我发现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。
如果您需要任何其他信息,请让我知道并感谢您的高级。
答
这里的问题是ARC不能告诉你用-performSelector:withObject:
调用的方法的内存管理语义是什么。在MRR下,这并不重要,因为调用代码需要相应地处理它(例如,如果它是一个拥有对象,则释放返回值)。但是在ARC下编译器需要才能知道这个信息是正确的。我不记得-performSelector:withObject:
的默认行为是什么,它可能只是将它视为非拥有的参考,在这种情况下,您并未实际泄漏。
处理这类代理模式的最简单方法是仍然使用-respondsToSelector:
,但是直接调用该方法,例如,
if ([_delegate respondsToSelector:@selector(foo:)]) {
[_delegate foo:self];
}
在你的情况下,该方法本身并不知道选择器是什么。你最好的选择可能是完全抛弃这种方法,并让它的前呼叫者处理与代表交谈。
将不可能添加一个“假”类别NSObject声明此方法?只是为了“拼出”语义...... – nielsbot 2012-03-20 01:23:38
@nielsbot:问题不在于缺少方法的声明。问题是编译器甚至不知道他试图调用什么方法,无论声明如何,因为他使用动态选择器来调用它。 – 2012-03-20 02:33:02
当然你是对的。没关系。 – nielsbot 2012-03-20 07:20:50