NSArrayM 在枚举时发生了突变
Posted
技术标签:
【中文标题】NSArrayM 在枚举时发生了突变【英文标题】:NSArrayM was mutated while being enumerated 【发布时间】:2012-09-21 04:41:10 【问题描述】:应用程序因错误而崩溃:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x21481c10> was mutated while being enumerated.'
只有当我在加载注释时移动到 mapview 时才会发生这种情况。如果我不触摸地图,则不会发生错误。
- (void) startloading
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^
[self loadPList];
);
我的代码是:
- (void) loadPList
@autoreleasepool
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [[documentPaths lastObject] stringByAppendingPathComponent:@"test.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSMutableArray *annotations = [[NSMutableArray alloc]init];
NSMutableArray * annotationsToRemove = [ mapView.annotations mutableCopy ] ;
[ annotationsToRemove removeObject:mapView.userLocation ] ;
[ mapView removeAnnotations:annotationsToRemove ] ;
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"blackKey"])
NSArray *ann = [dict objectForKey:@"Black"];
for(int i = 0; i < [ann count]; i++)
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:@"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:0] doubleValue];
MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
myAnnotation.title = [[ann objectAtIndex:i] objectForKey:@"Name"];
myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:@"Address"];
myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:@"Icon"];
[mapView addAnnotation:myAnnotation]; // SIGNAL SIGABRT
[annotations addObject:myAnnotation];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"blueyellowKey"])
NSArray *ann = [dict objectForKey:@"BlueYellow"];
for(int i = 0; i < [ann count]; i++)
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:@"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:0] doubleValue];
MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
myAnnotation.title = [[ann objectAtIndex:i] objectForKey:@"Name"];
myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:@"Address"];
myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:@"Icon"];
[mapView addAnnotation:myAnnotation];
[annotations addObject:myAnnotation];
【问题讨论】:
【参考方案1】:我认为您应该将您的 loadPlist
方法更改为此,然后调用 [self loadPlist]
来调用它:
- (void) loadPList
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [[documentPaths lastObject] stringByAppendingPathComponent:@"test.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
//ALL THIS CODE FROM HERE ON OUT IS NOT THREAD SAFE! YOU ARE ACCESSING THE UI AND MUST PERFORM IT ON THE MAIN THREAD!
dispatch_async(dispatch_get_main_queue(), ^
NSMutableArray *annotations = [[NSMutableArray alloc]init];
NSMutableArray * annotationsToRemove = [ mapView.annotations mutableCopy ] ;
[ annotationsToRemove removeObject:mapView.userLocation ] ;
[ mapView removeAnnotations:annotationsToRemove ] ;
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"blackKey"])
NSArray *ann = [dict objectForKey:@"Black"];
for(int i = 0; i < [ann count]; i++)
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:@"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:0] doubleValue];
MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
myAnnotation.title = [[ann objectAtIndex:i] objectForKey:@"Name"];
myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:@"Address"];
myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:@"Icon"];
[mapView addAnnotation:myAnnotation]; // SIGNAL SIGABRT
[annotations addObject:myAnnotation];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"blueyellowKey"])
NSArray *ann = [dict objectForKey:@"BlueYellow"];
for(int i = 0; i < [ann count]; i++)
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:@"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:0] doubleValue];
MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
myAnnotation.title = [[ann objectAtIndex:i] objectForKey:@"Name"];
myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:@"Address"];
myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:@"Icon"];
[mapView addAnnotation:myAnnotation];
[annotations addObject:myAnnotation];
);
这会在后台执行读取注释的 IO 工作,然后将 UI 工作传递回主线程。希望这会有所帮助!
【讨论】:
@PavelKaljunen 哪个对象在泄漏? NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; 如果我删除 dispatch_async,那么它就不会泄漏 内层还是外层?另外,对于您使用不同代码的两个问题,我不确定您到底在做什么。你为什么不解决这个问题,并用你当前的代码更新你的内存泄漏问题 - 你的 loadPlist 实现和你调用它的地方,以及任何指示泄漏的仪器结果。这真的会帮助我帮助你。 非常感谢您的帮助!我更新了这个问题:***.com/questions/12653016/…以上是关于NSArrayM 在枚举时发生了突变的主要内容,如果未能解决你的问题,请参考以下文章
NSArraym 在枚举时发生了变异,sqlite3 while 循环?
集合 <__NSSetM: 0x14ea0160> 在枚举时发生了突变