收集<calayerarray:0x1ed8faa0 =“”>在被枚举时被突变</calayerarray:>

时间:2013-02-13 13:16:00

标签: iphone ios objective-c

从屏幕移除等待视图时,我的应用程序崩溃了一段时间。请指导我如何改进下面给出的代码。


等待视图仅在应用程序从服务器下载内容时调用。当它完成下载后,我调用removeWaitView方法。

异常类型:NSGenericException

原因:收集在枚举时发生了变异。

+(void) removeWaitView:(UIView *) view{
    NSLog(@"Shared->removeWaitView:");
    UIView *temp=nil;
    temp=[view viewWithTag:kWaitViewTag];
    if (temp!=nil) {
        [temp removeFromSuperview];
    }
}

我的waitview添加代码是

 +(void) showWaitViewInView:(UIView *)view withText:(NSString *)text{
   NSLog(@"Shared->showWaitViewWithtag");
   UIView *temp=nil;
   temp=[view viewWithTag:kWaitViewTag];
   if (temp!=nil)
   {
       return;
   }
   //width 110 height 40
   WaitViewByIqbal *waitView=[[WaitViewByIqbal alloc] initWithFrame:CGRectMake(0,0,90,35)];
   waitView.center=CGPointMake(view.frame.size.width/2,(view.frame.size. height/2) -15); 
   waitView.tag=kWaitViewTag;    // waitView.waitLabel.text=text;
   [view addSubview:waitView];
   [waitView release]; 
}

3 个答案:

答案 0 :(得分:16)

异常非常清楚 - 一个集合(在这种情况下类似于数组)正在被枚举时被修改。

在这个特定情况下,我们讨论的是层数组,或者更好的说,UIView的实例都是由层支持的。

当您致电removeFromSuperviewaddSubview时,会发生修改。枚举可以在重绘期间随时进行。

我的猜测是 - 你没有从主线程调用你的方法,主线程当前正在重绘,所以你会得到一个赛车条件。

解决方案:仅从主线程调用这些方法。

答案 1 :(得分:6)

您应该获得该阵列的副本,因此在您的代码枚举时,您不会冒被修改的风险。当然,这可能会因为突变而添加新项目,因此您的枚举将错过一个数组项。以下是您问题标题的具体示例:

[[viewLayer.sublayers copy] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            CALayer * subLayer = obj;
            if(subLayer == theLayerToBeDeleted){
                [subLayer removeFromSuperlayer];
            }

        }];

答案 2 :(得分:3)

在迭代waitView的兄弟节点时,你可能会添加或删除waitView(它是superView的子视图)。检查调用removeWaitViewshowWaitInView的方法,以确保调用方法不会在for循环中调用show / remove等待视图方法迭代等待视图的兄弟节点(waitView的superview的子视图)