Iphone 收藏<;CALayerArray:0x1ed8faa0>;在枚举时发生了变异
从屏幕上删除等待视图时,我的应用程序崩溃了一段时间。请指导我如何改进下面给出的代码Iphone 收藏<;CALayerArray:0x1ed8faa0>;在枚举时发生了变异,iphone,ios,objective-c,Iphone,Ios,Objective C,从屏幕上删除等待视图时,我的应用程序崩溃了一段时间。请指导我如何改进下面给出的代码 仅当应用程序正在从服务器下载某些内容时,才会调用“等待”视图。当它完成下载后,我调用removeWaitView方法 异常类型:NSGenericeException 原因:集合在枚举时发生了变异 +(void) removeWaitView:(UIView *) view{ NSLog(@"Shared->removeWaitView:"); UIView *temp=nil;
仅当应用程序正在从服务器下载某些内容时,才会调用“等待”视图。当它完成下载后,我调用removeWaitView方法 异常类型:NSGenericeException 原因:集合在枚举时发生了变异
+(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];
}
例外情况很明显——一个集合(在本例中类似于数组)在被修改的同时也在被枚举
+(void) removeWaitView:(UIView *) view{
NSLog(@"Shared->removeWaitView:");
UIView *temp=nil;
temp=[view viewWithTag:kWaitViewTag];
if (temp!=nil) {
[temp removeFromSuperview];
}
}
在本例中,我们讨论的是层的数组,或者更好地说,是由层备份的UIView
的实例
在调用removeFromSuperview
或addSubview
时会发生修改。枚举可以在重绘期间随时发生
我的猜测是-您没有从主线程调用您的方法,并且主线程当前正在重新绘制,因此您将获得一个竞速条件
解决方案:仅从主线程调用这些方法。在遍历waitView的同级(它是superView的子视图)时,您可能在waitView中添加或删除一个对象。检查哪些方法调用了
removeWaitView
和showWaitInView
,以确保调用方法不会在for循环中调用show/remove wait view方法,该循环迭代wait view的兄弟(waitView的superview的子视图)。您应该获得数组的副本,因此,在代码枚举时,您不会冒被修改的风险。当然,这留下了一个机会,一个新的项目可能会被添加作为突变的结果,因此您的枚举将错过一个数组项目。以下是问题标题的具体示例:
[[viewLayer.sublayers copy] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
CALayer * subLayer = obj;
if(subLayer == theLayerToBeDeleted){
[subLayer removeFromSuperlayer];
}
}];
查看异常的完整回溯将非常有用。(如果您不确定如何查找此信息,您可能可以在Google上搜索。)如何调用
removeWaitView
?嗯。我总是尝试在主线程上调用类似的方法,但在我看来您是对的,因为此异常只能在未从主线程调用时出现(根据我的代码)。开发者亚伦·海曼的回答是另一种可能的解释。从堆栈跟踪中可以明显看出。非常聪明的分析。谢谢。是的,如果我在循环中使用过,这可能会产生问题。不,我不是在循环中使用它。由于我已经编辑了我的问题,非常感谢您的帮助。通常,循环内的显性突变是最常见的罪魁祸首。但是突变也可能发生在另一个线程中(sulthan指出)。