问题描述
多年来我一直在关注一个名为Target-Action的伟大模式,如下所示:
For years I've been following a great pattern called Target-Action which goes like this:
对象在指定的目标对象上调用指定的选择器时间来了。这在许多不同的情况下非常有用,你需要对任意方法进行简单的回调。
An object calls a specified selector on a specified target object when the time comes to call. This is very useful in lots of different cases where you need a simple callback to an arbitrary method.
这是一个例子:
- (void)itemLoaded {
[specifiedReceiver performSelector:specifiedSelector];
}
在ARC下,现在发现这样的事情突然变成了危险。
Under ARC it now turns out that doing something like this all of a sudden became dangerous.
Xcode会发出如下警告:
Xcode throws a warning that goes like this:
当然,选择器是未知的,因为作为Target-Action设计模式的一部分,您可以指定你想要什么样的选择器,以便在有趣的事情发生时接到一个电话。
Of course the selector is unknown since as part of the Target-Action design pattern you can specify whatever selector you want in order to get a call when something interesting happens.
这个警告最让我担心的是它可能存在潜在的内存泄漏。根据我的理解,ARC不会弯曲内存管理规则,而只是在正确的位置自动插入保留/释放/自动发布消息。
What bugs me most about this warning is that it says there can be a potential memory leak. From my understanding ARC doesn't bend the memory management rules but instead simply automates the insertion of retain/release/autorelease messages at the right locations.
此处需要注意的另一件事:-performSelector:确实有一个 id
的返回值。 ARC分析方法签名,以便在方法返回+1保留计数对象时通过应用命名约定来确定。在这种情况下,ARC不知道选择器是否是一个 -newFooBar
工厂,或者只是调用一个不可靠的工人方法(无论如何,这几乎都是Target-Action的情况)。实际上ARC应该已经认识到我不期望返回值,因此忘记任何可能的+1保留计数返回值。从这个角度来看,我可以看到ARC的来源,但仍然存在太多关于这在实践中意味着什么的不确定性。
Another thing to note here: -performSelector: does have an id
return value. ARC analyzes method signatures to figure out through application of naming conventions if the method returns a +1 retain count object or not. In this case ARC doesn't know if the selector is a -newFooBar
factory or simply calling an unsuspicious worker method (which is almost always the case with Target-Action anyways). Actually ARC should have recognized that I don't expect a return value, and therefore forget about any potential +1 retain counted return value. Looking at it from that point of view I can see where ARC is coming from, but still there is too much uncertainty about what this really means in practice.
现在这意味着在ARC下会出现哪些问题,如果没有ARC,这种情况永远不会发生?我不知道这会如何产生内存泄漏。有人可以提供这样做的危险情况的例子吗,以及在这种情况下如何创建泄密?
Does that now mean under ARC something can go wrong which would never happen without ARC? I don't see how this could produce a memory leak. Can someone give examples of situations in which this is dangerous to do, and how exactly a leak is created in that case?
我真的用谷歌搜索了网络但是没有找到任何网站解释为什么。
I really googled the hell out of the internet but didn't find any site explaining why.
推荐答案
的问题performSelector
是ARC不知道将执行的选择器是什么。请考虑以下事项:
The problem with performSelector
is that ARC doesn't know what the selector which will performed, does. Consider the following:
id anotherObject1 = [someObject performSelector:@selector(copy)];
id anotherObject2 = [someObject performSelector:@selector(giveMeAnotherNonRetainedObject)];
现在,ARC如何知道第一个返回保留计数为1但第二个返回的对象返回一个自动释放的对象? (我只是在这里定义一个名为 giveMeAnotherNonRetainedObject
的方法,它返回一些自动释放的东西)。如果它没有在任何版本中添加,那么 anotherObject1
将在这里泄漏。
Now, how can ARC know that the first returns an object with a retain count of 1 but the second returns an object which is autoreleased? (I'm just defining a method called giveMeAnotherNonRetainedObject
here which returns something autoreleased). If it didn't add in any releases then anotherObject1
would leak here.
显然在我的例子中选择器为实际上是已知的,但想象一下它们是在运行时选择的。 ARC真的无法在这里输入正确数量的保留
或发布
,因为它根本就没有我不知道选择器会做什么。你是对的,ARC没有弯曲任何规则,它只是为你添加正确的内存管理调用,但这正是它无法在这里做的事情。
Obviously in my example the selectors to be performed are actually known, but imagine that they were chosen at run time. ARC really could not do its job of putting in the right number of retain
s or release
s here because it simply doesn't know what the selector is going to do. You're right that ARC is not bending any rules and it's just adding in the correct memory management calls for you, but that's precisely the thing it can't do here.
你是对的,你忽略了返回值的事实意味着它会好起来,但总的来说ARC只是挑剔和警告。但我猜这就是为什么它是警告而不是错误。
You're right that the fact you're ignoring the return value means that it's going to be OK, but in general ARC is just being picky and warning. But I guess that's why it's a warning and not an error.
编辑:
如果你真的确保你的代码没问题,你可以像这样隐藏警告:
If you're really sure your code is ok, you could just hide the warning like so:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[specifiedReceiver performSelector:specifiedSelector];
#pragma clang diagnostic pop
这篇关于在ARC下,Target-Action设计模式是不是很糟糕?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!