7

编辑:这个问题也适用于普通声明的属性(不仅适用于类属性)!

原帖:

假设我有sharedInstance当前作为 getter 方法实现的公共类方法:

@interface MyClass

+ (instancetype)sharedInstance;

- (void)doSomething;

@end

@implementation MyClass

+ (instancetype)sharedInstance {
    static MyClass *shared = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shared = [[MyClass alloc] init];
    });
    return shared;
}

@end

在 Swift 3.0 中访问这个方法看起来像这样:MyClass.shared().doSomething()

所以为了让它更快捷,我们应该将类方法更改为类属性(Xcode 8 中的新功能。但实际上我在 Apple Docu 中找不到它,仅在 WWDC 2016 视频中)

@interface MyClass

@property (class, nonatomic, readonly) MyClass *sharedInstance;

- (void)doSomething;

@end

// implementation stays the same

现在在 Swift 代码中:MyClass.shared.doSomething()

那么nonatomic/atomic属性修饰符(不知道确切的术语)对于我自己在 objc 中实现的 getter 方法是否有意义?

4

2 回答 2

5

由于多种原因, atomic/nonatomic修饰符对您的情况无效。

主要原因是原子性关键字只影响生成的代码(即合成访问器方法)。当您@property在接口中声明 a 然后在实现中使用方法(或方法对)实现它时,编译器不会生成代码,因此您的 atomicity 关键字将被忽略。

有几种方法可以解决这种情况,您会触发其中的几种:

  • 首先,你class有财产。编译器无法为类属性合成访问器或存储——这意味着没有代码生成,因此原子性不适用。

  • 其次,在最常见的readonly属性使用中,@property声明由手动实现的 getter 方法支持——这意味着没有代码生成,因此原子性不适用。

    (请注意,您还可以readonly在公共接口中声明实例属性并由于实现中的私有readwrite重新声明而合成。在这种情况下,不仅原子性适用,您还必须使原子性关键字在公共和私有声明之间匹配。你也可以只合成一个 getter 并在你的实现中直接使用支持的 ivar。)

因为为这个属性指定atomic或指定nonatomic任何一种方式都不起作用,所以您可以自由地将原子性关键字完全留在您的声明之外。(编译器将假设atomic,但如前所述,假设无效。)

于 2016-11-07T18:59:13.253 回答
1

这很有意义。属性的声明为类信息的用户提供。允许该类的用户从 - 综合或手动 - 实现中期待您在声明中所说的内容。用户甚至无法知道它是否合成。

如果您自己实现 getter(或任何访问器),则应在属性声明中反映实现的原子性。如果您有非原子实现,则应将其添加到声明的属性中。

于 2016-11-07T21:03:53.220 回答