如何实现Objective-C属性的懒惰评估,可能是零?

时间:2014-03-24 15:48:33

标签: 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 {
    if (_lazyProp == nil) {
        _lazyProp = <Some Calculation>;
    }
    return _lazyProp
}

@end

1 个答案:

答案 0 :(得分:-3)

更新:这个答案是不安全的。请参阅下面的Yan的评论。离开这里,所以有相同想法的人可以提防。


使用dispatch_once代替检查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_once的标准代码段定义了一个静态onceToken,它在这里无法正常工作;初始化块仅对该类的第一个对象执行。