Objective-C中的私有变量是强引用吗?

7

在 Stack Overflow 上搜索,这似乎是在 Objective-C 中创建私有变量的方法:

@interface ClassName()
{
@private
    NSArray* private;
}
@property (strong, nonatomic) NSArray* public;
@end

现在这就是我困惑的地方。该属性声明为(strong,nonatomic),但私有变量并没有这样的声明。那么,ARC 如何知道它是否是 strong 的?

5
FYI - 你发布的代码是旧的方法。现在私有变量应该放在.m文件中的@implementation块中。而且,对于属性,没有必要声明ivar。也不需要显式调用@synthesize。只需在.h中声明@property即可。编译器将自动合成ivar。 - rmaddy
3个回答

13

实例变量默认情况下是__strong

引用自苹果的 ARC 过渡指南,关于变量(假定包括实例变量):

__strong 是默认值

稍后又写道:

使用 ARC,实例变量默认为强引用——将对象直接赋给实例变量确实会延长对象的生命周期

在通过@synthesize将属性连接到 ivar 之前,这个规则一直有效。此时,属性的所有权限定符会优先起作用。但是,如果你将属性声明为除了 strong 以外的任何类型,然后手动实现设置器和访问器,你就必须手动声明备份 ivar 的所有权限定符。


9
在属性的情况下,关联实例变量的所有权隐含于该属性的所有权中:
参见http://clang.llvm.org/docs/AutomaticReferenceCounting.html
如果一个属性被合成,则关联的实例变量是由@synthesize声明命名(可能是隐式的)的实例变量。如果关联的实例变量已经存在,则其所有权限定必须等于属性的所有权;否则,将使用该所有权限定创建实例变量。
一般来说,Objective-C对象默认为strong:
如果一个对象被声明为retainable object owner类型但没有显式的所有权限定符,则其类型将隐式调整为具有__strong限定符。
请注意,自LLVM 4.0编译器(Xcode 4.4)以来,@synthesize语句和关联的实例变量会自动创建,因此您只需要声明属性即可。

3

@property中的修饰符指定了生成的setter和其他ARC插入代码的行为。变量本身并不是强或弱的,它们只是内存位置。所以你现在编码的是强引用。

将其声明为强引用私有变量的方法是在.m文件内部的类别中声明其为strong

// .h
// nothing

// .m
@interface ClassName()
@property (strong, nonatomic) NSArray* myStrongPrivateProperty;
@end

// that's it

5
“变量本身并不是强引用或弱引用,它们只是内存位置。” - 这个说法是错误的。所有的 Objective-C 对象都有默认为__strong(强引用)的所有权。 - Martin R
这是个比喻。那句话阐述了一个关于如何处理那些内存位置的约定。实例变量最终是结构体中的字节,它们不会被存储额外的位来解释在运行时应该如何处理它们。这是编译器表格。 - danh
4
有点像是说“实例变量没有类型,它们只是结构中的位”。变量由位表示并不改变其在语义上具有其他属性的事实。变量可以是__strong或_weak,无论是否存在@property - BJ Homer
真正的观点和好比喻都值得赞赏。这些事情是按照惯例决定的(就像我们可以制定一个规则,规定未经装饰的4个字节应被视为整数)。我对OP问题的理解是:ARC语义来自哪里?它们来自@property声明,无论您是否明确声明了结构体。 - danh
+1 是为了指示如何正确声明私有属性。 - Martin R

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