在Objective-C中的nonatomic和readonly属性

3

我已经有几次想要创建一个同时具有nonatomicreadonly属性的变量了。

这样做的好处是我可以重写getter方法并检查实例是否已经被创建。如果没有,我可以简单地创建它。

同时,我可以保护该变量免受被覆盖的影响。


.h

@property (strong, readonly, nonatomic) Foo *bar;

.m

- (Foo *)bar {
    if (!_bar) {
        _bar = [[Foo alloc] init];
    }

    return _bar;
}

每当我这样做时,编译器不会为我创建一个实例变量,所以_bar不存在。

为什么?如何创建一个readonlynonatomic属性?


你可以在类接口中添加 Foo *bar; 或者将其隐藏在类别 @interface SomeClass (){Foo *bar;} 中。 - mike-dutka
3个回答

6
您的属性声明是正确的。我认为问题在于,因为您的属性被声明为readonly,编译器没有自动合成一个底层实例变量。在这种情况下的解决方案是自己合成一个,使用如下代码:@synthesize bar = _bar;

2
Xcode只有在你没有自己提供getter(以及在可读写属性的情况下,setter)时才会自动合成属性。这是正确的答案。 - Martin R
2
我认为当您将属性声明为只读时,它不会自动执行此操作。 - Diego Allen
1
另一个选项是,在@implementation块中自己声明ivar,而不是使用@synthesize - rmaddy
1
@MarkAdams:如果您不提供getter方法,Xcode也会自动合成只读属性。简单的规则是:如果您提供了所有必要的访问器方法,Xcode就不会自动合成。 - Martin R
@MarkAdams 我只需要一行来声明一个 ivar。也许你在将花括号放在自己的行中计数。各有所好。 :) - rmaddy
显示剩余3条评论

2
你可以创建一个私有 setter:
@interface YourClass()  // In the .m file 

@property (strong, readwrite, nonatomic) Foo *bar;

@end

当给变量赋值时:

self.bar = [[Foo alloc] init];

编辑

马克·亚当的回答也是正确的。


这不正确。没有必要创建一个私有的setter。此外,ivar默认为__strong,因此_bar = [[Foo alloc] init]确实会保留它。 - Martin R
不,你不必合成该属性。那只是其中一种选择。但你需要撤回关于对象未被保留的说法。正如马丁所说,那是不正确的。 - rmaddy
+alloc 返回一个 +1 引用计数的对象。这个对象是被保留的。 - bbum

1
在实现中添加 @synthesize bar = _bar。

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