我在我的应用程序中使用Game Center,我发现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)我直接从Apple的网站上的例子中复制了这个,所以如果Apple建立它,代码不会出现错误吗?
2)我该如何解决这个问题?
就像一个FYI,我使用的是使用LLMV编译器3.1和标准(armv7)架构的Xcode 4.3.1。我也在使用ARC。
如果您需要任何其他信息,请告诉我并提前感谢您。
答案 0 :(得分:1)
这里的问题是ARC无法告诉您使用-performSelector:withObject:
调用的方法的内存管理语义。在MRR下,它并不重要,因为预期调用代码会相应地处理它(例如,如果它是拥有的对象,则通过释放返回值)。但是在ARC下,编译器需要才能知道这些信息是正确的。我不记得-performSelector:withObject:
的默认行为是什么,它可能只是将其视为非拥有参考,在这种情况下你实际上并没有泄漏。
处理这种委托模式的最简单方法是仍然使用-respondsToSelector:
但是直接调用该方法,例如
if ([_delegate respondsToSelector:@selector(foo:)]) {
[_delegate foo:self];
}
在您的情况下,方法本身实际上并不知道选择器是什么。你最好的选择可能是完全放弃这种方法,让它的前呼叫者处理与代表交谈。