9

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


仅当应用程序从服务器下载内容时才会调用等待视图。当它完成下载时,我调用 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]; 
}
4

3 回答 3

18

例外情况很明显 - 一个集合(在本例中类似于数组)正在被修改,同时它也在被枚举。

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

修改发生在您调用removeFromSuperview或时addSubview。枚举可以在重绘期间随时发生。

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

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

于 2013-02-13T13:21:53.643 回答
6

您应该获得数组的副本,这样您就不会冒在代码枚举它时修改它的风险。当然,这留下了可能由于突变而添加新项目的机会,因此您的枚举将错过该数组项目。这是特定于您的问题标题的示例:

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

        }];
于 2015-09-05T08:18:41.717 回答
3

您可能会在迭代 waitView 的兄弟姐妹(它是 superView 的子视图)时添加或删除 waitView。检查以查看调用了哪些方法removeWaitView,并showWaitInView确保调用方法不会从迭代等待视图的兄弟(waitView 的父视图的子视图)的 for 循环中调用显示/删除等待视图方法。

于 2013-02-13T13:25:34.163 回答