问题
在开发过程中对于 NSArray 和 NSMutableArray 等的使用不当,出现crash,在最近的开发中对于枚举 sublayers 操作遇到这样的错误。
1
| Collection <__NSArrayM: 0xxxxxxx> was mutated while being enumerated.
|
字面意思就是--集合(数组)在枚举时发生突变。
同时对可变数组进行两种操作:枚举和内容修改(添加或者删除)。对于枚举器而言,容易已经改变了,很可能访问到未分配的内存空间。所以这样做是很危险的。
解决
在网上找了下这样的问题,自己也实践了下,发现要对操作的数组进行一次mutableCopy。
1 2 3 4 5
| NSMutableArray *mutableArray = [[[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3",@"4", nil] mutableCopy]; [mutableArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [mutableArray removeObject:obj]; }];
|
解决这里还有个疑惑 UIView对象中的subviews成员,子视图removeFromSuperview时为什么不会有上述的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| UIView *v1 = [[UIView alloc] init]; UIView *v2 = [[UIView alloc] init]; UIView *v3 = [[UIView alloc] init]; UIView *v4 = [[UIView alloc] init]; [v1 addSubview:v2]; [v1 addSubview:v3]; [v1 addSubview:v4]; NSLog(@"修改之前 - %@",v1.subviews); for (UIView *v in v1.subviews) { if(v == v3) { [v removeFromSuperview]; } } NSLog(@"修改之后 - %@",v1.subviews);
|
以上述代码为例,其实修改前的v1.subviews对象和修改后的对象不是一个对象了,简单的说就是修改前后v1.subviews对象地址发生变化
修改前
1 2 3 4 5 6
| Printing description of v1->_subviewCache: <__NSArrayM 0x7a07f480>( <UIView: 0x79e79c90; frame = (0 0; 0 0); layer = <CALayer: 0x79e79b30>>, <UIView: 0x79e7aeb0; frame = (0 0; 0 0); layer = <CALayer: 0x79e7fd60>>, <UIView: 0x79e7e660; frame = (0 0; 0 0); layer = <CALayer: 0x79e78b60>> )
|
修改后
1 2 3 4 5
| Printing description of v1->_subviewCache: <__NSArrayM 0x7a0af2d0>( <UIView: 0x79e79c90; frame = (0 0; 0 0); layer = <CALayer: 0x79e79b30>>, <UIView: 0x79e7e660; frame = (0 0; 0 0); layer = <CALayer: 0x79e78b60>> )
|
到此问题解决了。虽然是一个小的问题。