Pro*_*ber 35 xcode memory-management objective-c ios automatic-ref-counting
多年来我一直在关注一个名为Target-Action的伟大模式,如下所示:
当调用时,对象在指定的目标对象上调用指定的选择器.这在需要对任意方法进行简单回调的许多不同情况下非常有用.
这是一个例子:
- (void)itemLoaded {
[specifiedReceiver performSelector:specifiedSelector];
}
Run Code Online (Sandbox Code Playgroud)
在ARC下,现在发现做这样的事情突然变得危险.
Xcode会发出如下警告:
PerformSelector可能导致泄漏,因为其选择器未知
当然,选择器是未知的,因为作为Target-Action设计模式的一部分,您可以指定您想要的任何选择器,以便在发生有趣的事情时接听电话.
这个警告最让我感到困惑的是它说可能存在潜在的内存泄漏.根据我的理解,ARC不会弯曲内存管理规则,而只是在正确的位置自动插入retain/release/autorelease消息.
另外需要注意的是:-performSelector:确实有一个id
返回值.ARC分析方法签名,以便在方法返回+1保留计数对象时通过应用命名约定来确定.在这种情况下,ARC不知道选择器是-newFooBar
工厂还是只是调用一个不可靠的工作方法(无论如何,这几乎都是Target-Action的情况).实际上,ARC应该已经认识到我不期望返回值,因此忘记任何可能的+1保留计数返回值.从这个角度来看,我可以看到ARC的来源,但仍然存在太多关于这在实践中意味着什么的不确定性.
这现在是否意味着在ARC下会出现一些错误,如果没有ARC,这种错 我不知道这会如何产生内存泄漏.有人可以举出这样做危险的情况,以及在这种情况下如何创建泄漏?
我真的用谷歌搜索了互联网,但没有发现任何网站解释原因.
mat*_*way 25
问题performSelector
是ARC不知道将执行的选择器是什么.考虑以下:
id anotherObject1 = [someObject performSelector:@selector(copy)];
id anotherObject2 = [someObject performSelector:@selector(giveMeAnotherNonRetainedObject)];
Run Code Online (Sandbox Code Playgroud)
现在,ARC如何知道第一个返回一个保留计数为1的对象,但第二个返回一个自动释放的对象?(我只是定义了一个名为giveMeAnotherNonRetainedObject
here 的方法,它返回一些自动释放的方法).如果它没有添加任何版本,那么anotherObject1
将在这里泄漏.
显然在我的例子中,要执行的选择器实际上是已知的,但想象它们是在运行时选择的.ARC真的无法在这里输入正确数量的retain
s或release
s,因为它根本不知道选择器将要做什么.你是对的,ARC没有弯曲任何规则而只是为你添加正确的内存管理调用,但这正是它在这里无法做到的事情.
你是对的,你忽略了返回值的事实意味着它会好起来,但总的来说ARC只是挑剔和警告.但我想这就是为什么它是一个警告,而不是一个错误.
编辑:
如果您确定您的代码没问题,您可以隐藏警告,如下所示:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[specifiedReceiver performSelector:specifiedSelector];
#pragma clang diagnostic pop
Run Code Online (Sandbox Code Playgroud)
警告应如下所示:
PerformSelector可能导致泄漏,因为其选择器未知.ARC不知道返回的id是否具有+1保留计数,因此无法正确管理返回对象的内存.
不幸的是,这只是第一句话.
现在的解决方案:
如果从-performSelector方法接收返回值,则除了忽略它之外,您无法对代码中的警告执行任何操作.
NSArray *linkedNodes = [startNode performSelector:nodesArrayAccessor];
Run Code Online (Sandbox Code Playgroud)
你最好的选择是:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
NSArray *linkedNodes = [startNode performSelector:nodesArrayAccessor];
#pragma clang diagnostic pop
Run Code Online (Sandbox Code Playgroud)
我的初始问题中的情况也是如此,我完全忽略了返回值.ARC应该足够智能,以便看到我不关心返回的id,因此匿名选择器几乎保证不是工厂,便利构造函数或任何东西.不幸的是,ARC不适用,所以适用同样的规则.忽略警告.
通过在项目构建设置中的"其他警告标志"下设置-Wno-arc-performSelector-leaks编译器标志,也可以对整个项目执行此操作.
或者,当您在所需文件旁边右侧的"目标">"构建阶段">"编译源"下添加该标记时,可以按文件抑制警告.
所有三个解决方案都非常混乱恕我直言,所以我希望有人想出一个更好的解决方案.
归档时间: |
|
查看次数: |
2773 次 |
最近记录: |