【问题标题】:NSArrayM was mutated while being enumeratedNSArrayM 在枚举时发生了突变
【发布时间】: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];              

            }

        }   



   }
}

【问题讨论】:

    标签: iphone xcode sigabrt dispatch mutated


    【解决方案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 实现和你调用它的地方,以及任何指示泄漏的仪器结果。这真的会帮助我帮助你。
    • 非常感谢您的帮助!我更新了这个问题:stackoverflow.com/questions/12653016/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 2012-07-30
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多