7

__weak在方法的实现签名中使用存储修饰符是否有效?特别是如果它不是方法的公共签名的一部分?例如:

- (UIView *)tableView:(__weak UITableView *)tableView viewForHeaderInSection:(NSInteger)sectionIndex
{
    UIView *view = [ABHeaderView view];
    view.actionBlock = ^{
        [tableView doSomething];
    }
    // ...
    return view;
}

这是否正确tableView用作弱指针?或者我真的应该做类似的事情__weak *weakTableView = tableView;weakTableView在块内使用吗?

我没有收到任何警告或错误,并且 clang 静态分析器不会引发任何警告。

4

2 回答 2

1

当涉及动态调度和覆盖时,不要指望存储修饰符或属性被“动态”尊重(1)。

此方法在 UIKit 中正式声明。使用 ARC 时编译器可能会出错,因为它可能会在调用时将选择器与原始声明匹配。也就是说,您的声明对 UIKit 不可见,如果它也被编译为 ARC,UIKit 会将其视为默认/强。如果声明不匹配,或者即使它们在客户端+调用者翻译中不可见,也可能发生这种情况。

参数类型/属性不是选择器的一部分,也不是动态分配的。ARC 在这里应该假设是强的,并且调用者持有引用。这个特定的例子可能不会导致运行时错误,但这是一个有问题的做法,我认为可以找到错误。我已经在这个答案中证明了这一点。从根本上说,这是一个类似的概念。

动态 objc 调度的简单规则:在重新声明、定义和覆盖时始终匹配原始声明的签名。唯一可能的例外是不会改变签名的 C 兼容限定符(我见过的 ObjC 程序中非常不常见的做法)。

(1) 从技术上讲,它不是覆盖,而是协议方法的实现。无论如何,sig 应该是相同的。

于 2012-04-17T12:59:07.673 回答
0

__strong__weak存储修饰符是您内部实现的一部分,据我所知。它们不会影响方法调用者生成的代码,所以我认为你现在很安全,将来很可能。

不过,我确实认为它的风格很差,因此您将引用复制到弱引用的建议似乎是一个很好的解决方案。

于 2012-04-17T11:19:39.937 回答