在目标C中,通常的做法是以懒惰的方式实例化内部类数组(等(。
因此,如果您调用 getter,它首先检查数组是否为 nil,并在需要时为其分配内存。
但是二传手呢?如果您尝试将一些值插入到其中一个数组单元格中,因为我们还没有为它分配内存 - 它去哪里了?
显然,我在这里错过了一些东西。很乐意澄清。
我不确定我是否理解您的问题,但如果您这样做:
@property (nonatomic, strong) NSMutableArray* myArray;
...
- (NSMutableArray *) myArray {
if(!_myArray) {
NSLog(@"created");
_myArray = [[NSMutableArray alloc] init];
}
return _myArray;
}
...
[self.myArray addObject:@"test"];
当您调用 addObject:
时,getter 实际上被调用,因此您将看到正在记录"已创建"。
因此,@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;
}));
}