关于OC中的for in循环

先看一下for in循环默认的语法

1
2
3
for (type *object in collection) {
statements
}

for in 遍历的本质

forin在遍历数组时,遍历的是数组中的每个元素, 在对字典快速遍历时,遍历的是字典中的key,然后通过key获取对应的value值 因此forin 里type对应的类型是key对应的对象类型

for in 与 for 的区别

两者在遍历时看着是完全一致的,比如下面这段代码:

1
2
3
4
5
6
7
8
9
10
//for in
for (NSString* str in arr) {
NSLog(@"%@", str);
}

//for
for (int i = 0; i < arr.count; i ++) {
NSString* str = [arr objectAtIndex:i];
NSLog(@"%@", str);
}

但本质上是有很大区别的。for in实际上是快速枚举,跟for循环意义上还是有区别的。

如果在for in 循环里,对这个数组进行了修改的话,无论是增,删,修改数组元素位置,都会扔一个异常出来,错误是枚举的过程中数组发生了突变。

1
2
//错误提示:枚举的过程中数组发生了突变
<__NSArrayM: 0xa4fc000> was mutated while being enumerated.

原因如下:

1.NSArray的枚举操作中有一条需要注意:对于可变数组进行枚举操作时,你不能通过添加或删除对象这类操作来改变数组容器。如果你这么做了,枚举器会很困惑,而你将得到未定义的结果。

2.而本身这种操作也是有问题的,数组容器已经改变,可能遍历到没有分配的位置,用for循环机器不能自己察觉,但是枚举器可以察觉。

一点小补充

在使用UIView对象的subview数组遍历时,就算removeFromSurperview,也不会出现上面的问题。

原因:一旦将UIView对象的subview removeFromSurperview之后,UIView对象的subviews数组,整个对象都不同了。(从对象指针可以看出来)并不是单纯的将subview从数组里面移除掉。