如何在 Objective-C 中懒惰地设置 BOOL 属性

Posted

技术标签:

【中文标题】如何在 Objective-C 中懒惰地设置 BOOL 属性【英文标题】:How to lazily set BOOL property in Objective-C 【发布时间】:2015-08-06 13:49:19 【问题描述】:

我需要一个数据结构上的 BOOL 属性,表示数据库中某个对象的状态,并且我想懒惰地设置该属性——也就是说,我不想在需要之前 ping 数据库,并且只在那个时候设置属性(即我第一次得到它时)。

对于像 NSString 这样的东西,我会做一个像

这样的 getter
- (NSString *)myString 
    if (!_myString) 

        // ask db for value
        _myString = [value returned from db]

    
    return _myString;

但在 Objective-C 中,BOOL 似乎默认为 NO——这意味着我永远不会知道该值是否实际上是 NO,或者我还没有得到它。我已经四处寻找,但我似乎无法弄清楚如何为这样的属性创建我想到的那种吸气剂。有什么建议?还是我错过了一些非常明显的东西?提前致谢。

【问题讨论】:

你可以使用一个也可以存储真/假值的 NSNumber 而不是 bool,然后你可以测试 NSNumber 是否为 nil 你也可以只使用一个初始化为 -1 的 int,然后你可以将它设置为 0 或 1,如果它是真或假,你可以知道它还没有被延迟加载,如果它 - 1 @Fonix 使用 int 是个好主意 使用整数很好。您也可以只使用两个布尔值,一个用于保存值,另一个用于指示第一个是否有效/已被初始化。 【参考方案1】:

您可以在对象内部使用 NSNumber:

// .h
@interface Object : NSObject

@property (nonatomic, assign) BOOL myBool;

@end

//.m
@interface Object ()

@property (nonatomic, strong) NSNumber *myBoolFromDB;

@end

@implementation Object

- (BOOL) myBool 
    if (_myBoolFromDB == nil) 
        ...
    
    return [_myBoolFromDB boolValue];


@end

【讨论】:

【参考方案2】:

如果您只需要进行一次初始化,并且每个类的实例不需要一次dispatch_once() 可能是一个不错的工具:

- (BOOL)myBool 
    static dispatch_once_t once;
    dispatch_once(&once, ^
        // initialize _myBool here
    );
    return _myBool;

从实际的角度来看,它与其他解决方案并没有太大的不同:您需要记住您是否已经初始化了状态不知何故,以及是否通过将状态存储在指针中来完成可以是 nil,或者在一个 int 中可以有一些“未初始化”的值,或者在一个静态的 once 变量中编码并没有太大区别。

不过,我喜欢这种方法的地方在于,它清楚地传达了您的意图:您希望这件事仅在第一次调用 myBool 时发生。它还允许您将myBool 属性存储为BOOL,而不是您必须转换为BOOL 的其他类型,这再次更清楚地传达了您的意图。

【讨论】:

如果你不明白你在做什么,这是非常危险的。如果该类有多个实例,那么这将无法正常工作。该类只有一个 once 变量,而不是每个实例一个。因此,一旦在任何实例上调用了 -myBool,“在此处初始化 _myBool”代码将为该实例运行,然后不再运行,无论是该实例还是其他任何实例。 @KenThomases 完全同意!我可能在这里假设太多了。我会编辑以明确这一点。感谢您了解这一点。

以上是关于如何在 Objective-C 中懒惰地设置 BOOL 属性的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法懒惰地获取@Embedded 字段?

RxSwift:如何使用 shareReplay 懒惰地获取订阅

如何标记多个资源从属性中懒惰地读取它们?

如何从 Python 中的文件/流中懒惰地读取多个 JSON 值?

在 Python 中懒惰地转置一个列表

我如何懒惰地从Rust中的文件/流中读取多个JSON值?