从屏幕移除等待视图时,我的应用程序崩溃了一段时间。请指导我如何改进下面给出的代码。
等待视图仅在应用程序从服务器下载内容时调用。当它完成下载后,我调用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];
}
答案 0 :(得分:16)
异常非常清楚 - 一个集合(在这种情况下类似于数组)正在被枚举时被修改。
在这个特定情况下,我们讨论的是层数组,或者更好的说,UIView
的实例都是由层支持的。
当您致电removeFromSuperview
或addSubview
时,会发生修改。枚举可以在重绘期间随时进行。
我的猜测是 - 你没有从主线程调用你的方法,主线程当前正在重绘,所以你会得到一个赛车条件。
解决方案:仅从主线程调用这些方法。
答案 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的子视图)。检查调用removeWaitView
和showWaitInView
的方法,以确保调用方法不会在for循环中调用show / remove等待视图方法迭代等待视图的兄弟节点(waitView的superview的子视图)