objective-c - Target-Action 设计模式是否在 ARC 下变成了坏习惯?

标签 objective-c ios xcode memory-management automatic-ref-counting

多年来,我一直在遵循一种名为 Target-Action 的伟大模式,它是这样的:

一个对象在调用的时候调用指定目标对象上的指定选择器。这在您需要对任意方法进行简单回调的许多不同情况下非常有用。

这是一个例子:

- (void)itemLoaded {
    [specifiedReceiver performSelector:specifiedSelector];
}

在 ARC 下,现在发现做这样的事情突然变得很危险。

Xcode 抛出如下警告:

PerformSelector may cause a leak because its selector is unknown

当然,选择器是未知的,因为作为 T​​arget-Action 设计模式的一部分,您可以指定您想要的任何选择器,以便在发生有趣的事情时得到调用。

这个警告最让我烦恼的是它说可能存在内存泄漏。根据我的理解,ARC 不会改变内存管理规则,而是简单地在正确的位置自动插入保留/释放/自动释放消息。

这里要注意的另一件事:-performSelector: 确实有一个 id 返回值。 ARC 分析方法签名,通过应用命名约定来确定方法是否返回 +1 保留计数对象。在这种情况下,ARC 不知道选择器是 -newFooBar 工厂还是只是调用了一个不可疑的 worker 方法(Target-Action 几乎总是这样)。实际上 ARC 应该已经认识到我不期望返回值,因此忘记任何潜在的 +1 保留计数返回值。从这个角度来看,我可以看到 ARC 的来源,但对于这在实践中的真正含义仍然存在太多不确定性。

现在这是否意味着在 ARC 下可能会出现一些没有 ARC 永远不会发生的错误?我不明白这怎么会产生内存泄漏。有人可以举例说明在哪些情况下这样做很危险,以及在这种情况下究竟是如何造成泄漏的?

我真的在互联网上用谷歌搜索了 hell ,但没有找到任何网站解释原因

最佳答案

performSelector 的问题在于 ARC 不知道选择器将执行什么操作。请考虑以下事项:

id anotherObject1 = [someObject performSelector:@selector(copy)];
id anotherObject2 = [someObject performSelector:@selector(giveMeAnotherNonRetainedObject)];

现在,ARC 怎么知道第一个返回一个保留计数为 1 的对象,而第二个返回一个自动释放的对象? (我只是在这里定义了一个名为 giveMeAnotherNonRetainedObject 的方法,它会返回自动释放的内容)。如果它没有添加任何版本,那么 anotherObject1 将在此处泄漏。

显然,在我的示例中,要执行的选择器实际上是已知的,但可以想象它们是在运行时选择的。 ARC 确实无法在此处完成放入正确数量的 retainrelease 的工作,因为它根本不知道选择器将要做什么。你是对的,ARC 没有违反任何规则,它只是为你添加正确的内存管理调用,但这正是它不能在这里做的事情。

你是对的,你忽略返回值的事实意味着它会没问题,但一般来说,ARC 只是挑剔和警告。但我想这就是为什么它是警告而不是错误的原因。

编辑:

如果你真的确定你的代码没问题,你可以像这样隐藏警告:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[specifiedReceiver performSelector:specifiedSelector];
#pragma clang diagnostic pop

关于objective-c - Target-Action 设计模式是否在 ARC 下变成了坏习惯?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8855461/

相关文章:

objective-c - IOS:使用 iPad KeyBoard 的回车键操作

ios - 在 tableView Cell 中看不到按钮的图像

objective-c - 遍历特定类型的所有 subview

iphone - 为XCODE项目(IPHONE)配置tesseract

ios - (iOS) 增加与 GameScene 相关的内存消耗

objective-c - 按分隔符拆分字符串

objective-c - 实例变量的分配?

ios - 在 loginView 中解析背景图像,不适合所有 iPhone 设备的屏幕尺寸

ios - UIPickerView 选择指示器在 iOS10 中不可见

ios - GoogleCloudMessaging 链接错误