Aks*_*kar 22 objective-c nsmutablearray nsarray ios
我犯了一个错误,同时创造一个TableView中class,并且意外地保持我@property的copy,当我定义它:
@property (copy, nonatomic) NSMutableArray *words;
Run Code Online (Sandbox Code Playgroud)
我正确地初始化了数组:(注意这是第三次尝试,所以请忽略我不使用mutableCopy和其他更好的方法这样做的事实)
NSArray *fixedWords = @[@"Eeny", @"Meeny", @"Miny", @"Moe", @"Catch", @"A", @"Tiger", @"By", @"His", @"Toe"];
NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords];
self.words = mutWords;
Run Code Online (Sandbox Code Playgroud)
但是当我后来重新排序数组时,它在removeObjectAtIndex行崩溃:
id object = [self.words objectAtIndex:fromIndexPath.row];
NSUInteger from = fromIndexPath.row;
NSUInteger to = toIndexPath.row;
[self.words removeObjectAtIndex:from];
Run Code Online (Sandbox Code Playgroud)
带有错误消息
unrecognized selector sent to instance
Run Code Online (Sandbox Code Playgroud)
进行了大量的挖掘,以确定这是因为复制意味着分配NSMutableArray会导致创建标准(不可变)NSArray.任何人都可以解释为什么这是正确的行为?
Cod*_*aFi 36
-copy,由可变的Cocoa类实现,总是返回它们的不可变对应物.因此,当发送NSMutableArray -copy时,它返回包含相同对象的NSArray.
因为words有内存限定符copy,这一行:
NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords];
self.words = mutWords;
Run Code Online (Sandbox Code Playgroud)
扩展到:
NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords];
self.words = [mutWords copy];
Run Code Online (Sandbox Code Playgroud)
鉴于NSMutableArray的是NSArray中的一个子类,编译器不抱怨,你现在有你的手一个定时炸弹,因为NSArray中不承认它的可变子类的方法(因为它不能发生变异它的内容).
属性并不神奇,它们只是简写.声明@property对象会告诉编译器为它创建一个支持实例变量和访问器方法.实际生成的代码取决于您在属性上设置的属性.
重要的是要记住,使用点语法设置属性也是简写.你打电话的时候…
self.words = mutWords;
Run Code Online (Sandbox Code Playgroud)
...你实际上是在幕后调用生成的访问器方法,如下所示:
[self setWords:mutWords];
Run Code Online (Sandbox Code Playgroud)
由于您在copy属性上指定了该属性,因此您已告诉编译器-setWords:使用如下所示的代码生成该访问器方法:
- (void)setWords:(NSMutableArray *)words
{
_words = [words copy];
}
Run Code Online (Sandbox Code Playgroud)
了解所有这些,您可以看到发生了什么:生成的setter方法将调用-copy输入参数,并将结果分配给后备实例变量.因为该-copy方法总是被实现为返回不可变对象(执行[aMutableString copy]将返回NSString,等等)设置该属性将始终存储不可变副本.
| 归档时间: |
|
| 查看次数: |
9215 次 |
| 最近记录: |