Objective-C属性 - 类别中的强引用和弱引用声明

10

Objective-C运行时如何处理一个在类中定义为weak的属性,但是该类的私有分类定义了一个同名同类型的strong属性?

在分类的上下文中运行的代码会使用原始(弱)修饰符,还是将使用分类定义的修饰符(强)?

例如:

Name.m

@property (weak, nonatomic) NSString *name;

NameTests.m

:测试名称代码文件。
@interface Name (Test)
@property (strong, nonatomic) NSString *name;
@end

6
好问题!我很惊讶这个代码居然能通过编译(不过你可以用一个小的测试程序找出它的运行结果)。 - Sergey Kalinichenko
2个回答

2
在属性声明中,weak 只适用于合成的setter方法(如果有的话)和合成的实例变量(如果有的话)。如果两者都没有合成,则weak 不起作用。
如果setter和实例变量被合成了,那么问题是:编译器使用哪个属性声明来合成setter和实例变量?
编译器永远不会合成在命名分类中声明的属性。因此,在您的示例中,name 是一个弱引用属性。

0

在运行时添加具有模糊名称的属性(当您使用类别扩展类时会发生这种情况)时,其行为未定义,因为无法确定使用哪个方法实现。
这只是一个命名冲突,可以通过给您的类别方法/属性添加前缀来避免。有关前缀的详细信息,请参阅苹果公司的"Programming With Objective-C"指南中的“避免类别方法名称冲突”部分。

当您构建一个简单的测试项目时,您可能会观察到运行时随机使用两个实现之一。(在测试时,避免使用常量字符串作为名称属性,因为它们不会暴露行为)

通过使用类扩展而不是命名类别,编译器将生成“属性的非法重新声明”错误。


1
命名冲突实际上是有意的。这是一种技术,可以使单元测试能够访问私有属性和方法。原始类别可以选择性地将私有属性和方法暴露给测试类,而无需破坏这些项在“真实”代码中的封装。请查看 https://engineering.aweber.com/improving-ios-unit-tests-with-ocmock 或 https://dev59.com/2nvaa4cB1Zd3GeqPFZ7G 中的“隐私不保证”。 - Andy Obusek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接