如何对可能为零的objective-C属性进行惰性评估?

如何对可能为零的objective-C属性进行惰性评估?,objective-c,thread-safety,lazy-loading,lazy-evaluation,lazy-initialization,Objective C,Thread Safety,Lazy Loading,Lazy Evaluation,Lazy Initialization,在objective-C中,如何正确实现对可能为零的属性的惰性评估 通常的做法如下所示,但是对于可能为零的属性,它不能正常工作-它们的初始化不会只执行一次 @interface LZClass: NSObject @property (strong, readonly) NSString * lazyProp; @end @implementation LZClass @synthesize lazyProp = _lazyProp; - (NSString *)lazyProp {

在objective-C中,如何正确实现对可能为零的属性的惰性评估

通常的做法如下所示,但是对于可能为零的属性,它不能正常工作-它们的初始化不会只执行一次

@interface LZClass: NSObject
@property (strong, readonly) NSString * lazyProp;
@end

@implementation LZClass

@synthesize lazyProp = _lazyProp;
- (NSString *)lazyProp {
    if (_lazyProp == nil) {
        _lazyProp = <Some Calculation>;
    }
    return _lazyProp
}

@end

更新:这个答案不安全。见下面严的评论。把它留在这里,让有相同想法的人小心

使用dispatch_一次,而不是检查nil

@interface LZClass: NSObject {
    dispatch_once_t _onceToken;
}
@property (strong, readonly) NSString * lazyProp;
@end

@implementation LZClass

@synthesize lazyProp = _lazyProp;
- (NSString *)lazyProp {
    dispatch_once(&_onceToken, ^{
        _lazyProp = <Some Calculation>;
    }
    return _lazyProp
}

@end
这还具有线程安全的优点。当初始化块已经执行时,试图读取属性的线程将被阻塞,并在初始化块返回后继续。因此,保证在所有线程中返回正确的结果


还要注意:dispatch_的标准代码段曾经定义了一个静态onceToken,它在这里无法正常工作;初始化块将只对类的第一个对象执行。

使用dispatch_一次,或者只使用一个单独的布尔变量。不能将dispatch_与实例变量一起用于谓词:谓词必须指向存储在全局或静态范围中的变量。使用包含Objective-C实例变量的自动或动态存储的谓词的结果是未定义的。看见