每
日OC冷知识:数组的可变性
在Objective-C中,有两种类型的数组:可变数组(NSMutableArray)和不可变数组(NSArray)。可变数组可以被改变,而不可变数组则不能。但是,你是否知道,在某些情况下,即使你定义了一个不可变数组,它仍然可能是可变的?
首先,让我们来看看一个简单的示例:
NSArray *immutableArray = @[@"Apple", @"Banana", @"Orange"];
[immutableArray addObject:@"Grapes"];
这段代码会导致编译错误,因为不可变数组是不能添加对象的。但是,如果我们将这段代码稍微修改一下:
id mutableObject = @[@"Apple", @"Banana", @"Orange"];
[mutableObject addObject:@"Grapes"];
NSArray *immutableArray = [NSArray arrayWithArray:mutableObject];
这段代码将不会导致编译错误,因为我们在第二行创建了一个id类型的指针,它指向了一个可变数组。在接下来的第三行中,我们将这个可变数组转换为一个不可变数组,并将其赋值给了immutableArray。现在,我们可以像下面这样去访问它:
NSLog(@"immutableArray: %@", immutableArray);
输出结果为:
2019-09-07 15:17:23.345 Demo[52474:441860] immutableArray: (
Apple,
Banana,
Orange,
Grapes
)
我们可以看到,这个不可变数组实际上已经改变了,因为我们在可变数组中添加了一个新的对象。但是,为什么我们能够这样做呢?
这是因为NSArray在内部其实是使用一个指向__NSArrayM(即可变数组)的指针。当你创建一个可变数组时,该指针指向这个可变数组,而当你创建一个不可变数组时,该指针指向__NSArrayI(即不可变数组)。但是,因为NSInteger、NSNumber等数据类型在数组中是以指针的模式存在的,所以我们仍然可以对这些对象进行操作。
那么,在什么情况下会出现这种情况呢?主要就是在使用框架提供的方法时,比如从Web API中获取数据或者从Core Data中查询数据。在这些方法中返回的数组都是不可变的,但是实际上可能是可变的。因此,在操作这些数组之前,你需要进行一些检查或者转换操作,以确保你使用的是正确的类型。
总结一下,虽然不可变数组是不能被改变的,但在某些情况下,它有可能是可变的。当我们使用框架提供的方法获取到一个不可变数组时,要特别注意其可变性,以免在使用时出现错误。