3

在 Objective C 中,以惰性方式实例化内部类数组(等)的常见做法。

因此,如果您调用 getter,它首先会检查数组是否不为零,并在需要时为其分配内存。

但是二传手呢?如果您尝试将一些值插入到数组单元之一中,因为我们还没有为它分配内存- 它去哪里了?

很明显,我在这里遗漏了一些东西。很高兴得到澄清。

4

2 回答 2

4

我不确定我是否理解您的问题,但如果您这样做:

@property (nonatomic, strong) NSMutableArray* myArray;
...

- (NSMutableArray *) myArray {
    if(!_myArray) {
        NSLog(@"created");
        _myArray = [[NSMutableArray alloc] init];
    }

    return _myArray;
}

...
[self.myArray addObject:@"test"];

当你调用 getter 时,实际上会被调用addObject:,所以你会看到“created”被记录下来。

于 2013-10-01T07:52:10.997 回答
3

所以@property 声明是语法糖,在对象的情况下,声明指向实例变量的指针。“非原子”是指自动创建的 getter 和 setter 的类型(在这种情况下是“非线程安全的”。)而“强”是 ARC 增加变量保留计数的指标。

所以当你声明:

@property (nonatomic, strong) NSMutableArray* myArray;

这是在您的类中真正创建的内容 - 只是指向您的隐藏实例变量的指针。

@implementation MyClass {
    NSMutableArray *_myArray;
}

正如您在 getter 中看到的,您正在初始化 _myArray 指针以指向一个新的 NSMutableArray:

- (NSMutableArray *) myArray {
    if(!_myArray) {
        NSLog(@"created");
        _myArray = [[NSMutableArray alloc] init];
    }

    return _myArray;
}

但是在 setter 中,您只是更新指向您已经创建的变量的指针。

self.myArray = [[NSMutableArray alloc] init];

这会向您的班级发送以下消息:

- (void) myArray: (NSMutableArray *) myArray {
    _myArray = myArray;
}

如您所见,大多数情况下,setter 不需要任何特殊的初始化。您想要创建自定义设置器的唯一时间是您想要验证传入对象是否具有特殊属性。一个人为的例子是检查 NSMutableArray 不大于 10 个对象:

- (void) myArray: (NSMutableArray *) myArray {
    if (myArray.count < 10) {
        _myArray = myArray;
    }
}

最后,我想指出的是,您实际上可以使用短三元运算符和括号返回值来延迟实例化对象。例如,以下语句:

- (NSMutableArray *) myArray {
    return (_myArray = _myArray ?: @{}.mutableCopy);
}

等于:

- (NSMutableArray *) myArray {
    if(!_myArray) {
        _myArray = [[NSMutableArray alloc] init];
    }
    return _myArray;
}

您甚至可以将此模式宏化为(WSM 是我的类前缀):

#define WSM_LAZY(object, assignment) (object = object ?: assignment)

所以你可以这样写语句:

- (NSMutableArray *) myArray {
    return WSM_LAZY(_myArray, @{}.mutableCopy);
}

甚至使用复合语句语法来重写您作为示例提供的原始 setter:

- (NSMutableArray *) myArray {
    return WSM_LAZY(_myArray, ({
        NSLog(@"created");
        @{}.mutableCopy;
    }));
}
于 2014-01-25T20:03:36.747 回答