使用__weak修改实现中参数的存储

时间:2012-04-17 08:48:12

标签: objective-c memory-management automatic-ref-counting objective-c-blocks

在方法的实现签名中使用__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 Static Analyzer不会发出任何警告。

2 个答案:

答案 0 :(得分:1)

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

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

参数类型/属性不是选择器的一部分,也不适用于动态分派。 ARC应该在这里强大,并且调用者保存引用。这个具体的例子可能不会导致运行时错误,但这是一个值得怀疑的做法,我认为可以找到错误。我已经为属性in this answer证明了这一点。从根本上说,这是一个类似的概念。

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

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

答案 1 :(得分:0)

就我所见,

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

我确实认为它的风格很差,所以你建议将参考文献复制到弱引用似乎是一个很好的解决方案。