2

iOS 6 でマップ ビューを読み込んでいるときに問題が発生しました。しかし、以前の OS バージョンでは 100% 動作しています。

コードは次のとおりです。

//.h file
MKMapView *galleryListMap; //map view
NSMutableArray *copyOfAllRecords; //array with locations

そして、これが私の .m ファイルのコード構造です。変数を合成し、deallocメソッドで解放しました。

//this will runs in a background thread and populateMap method will make all the   annotations
//[self performSelectorInBackground:@selector(populateMap) withObject:nil];

//here is populateMap method
-(void)populateMap{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; 
NSArray *existingpoints = galleryListMap.annotations;

//removes alll the existing points
[galleryListMap removeAnnotations:existingpoints];



//assign point to map view
for(int i = 0; i < [copyOfAllRecords count]; i++) {

     Gallery  *gallery = (Gallery *)[copyOfAllRecords objectAtIndex:i];//array which has the elements

     //create location based on the latitude and longtitude
     CGFloat latDelta = gallery.latitude;
     CGFloat longDelta = gallery.longitude;
     CLLocationCoordinate2D newCoord = {latDelta, longDelta};

      //adds the notations
     AddressAnnotation *addrAnnotation = [[[AddressAnnotation alloc] initWithCoordinate:newCoord]autorelease];
     //assing the location the map

    [addrAnnotation setId:i];
    [addrAnnotation setTitle:gallery.name];

    if([gallery.exhibition length]==0 && !gallery.isResturant){
        [addrAnnotation setSubtitle:@""];

    }else{
        [addrAnnotation setSubtitle:gallery.exhibition];
    }

    **//gives the exception on this line
    [galleryListMap addAnnotation:addrAnnotation];**

}

MKCoordinateRegion region;
MKCoordinateSpan span = MKCoordinateSpanMake(0.2, 0.2);
Gallery *lastGalleryItem = [copyOfAllRecords lastObject];
CLLocationCoordinate2D location = {lastGalleryItem.latitude, lastGalleryItem.longitude};

region.span=span;
region.center=location;

[galleryListMap setRegion:region animated:TRUE];
[galleryListMap regionThatFits:region];

galleryListMap.showsUserLocation = YES;

[pool release];

}

- (MKAnnotationView *) mapView:(MKMapView *)mkmapView viewForAnnotation:(AddressAnnotation *) annotation{


   static NSString *identifier = @"currentloc";

if([annotation isKindOfClass:[AddressAnnotation class]]){

    MKPinAnnotationView *annView = [[[MKPinAnnotationView alloc]initWithAnnotation:addAnnotation reuseIdentifier:identifier]autorelease];

    Gallery *galItem = (Gallery *)[copyOfAllRecords objectAtIndex:annotation.annotationId];

    CGRect viewFrame;
    UIView *myView;
    UIImage *tagImage;

     //checks whether the resturant or not
    if (galItem.isResturant) {

     viewFrame = CGRectMake( 0, 0, 41, 45 );
     myView = [[UIView alloc] initWithFrame:viewFrame];
     tagImage= [UIImage imageNamed:@"map_restaurant"];

    }else{

    viewFrame = CGRectMake( 0, 0, 41, 45 );
    myView = [[UIView alloc] initWithFrame:viewFrame];
    tagImage= [UIImage imageNamed:galItem.mapMarker];

    }


    UIImageView *tagImageView = [[UIImageView alloc] initWithImage:tagImage];
    [myView addSubview:tagImageView];
    [tagImageView release];


    UIGraphicsBeginImageContext(myView.bounds.size);
    [myView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();



    [annView setImage:viewImage];
    [myView release];

    int recordCount =[copyOfAllRecords count];


    if (recordCount != 0 ) {
        UIButton *annotationButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        [annotationButton addTarget:self action:@selector(showLinks:) forControlEvents:UIControlEventTouchUpInside];
        annotationButton.tag  = [annotation annotationId];
        annView.rightCalloutAccessoryView = annotationButton;
    }


    if([annotation annotationId]==recordCount-1){
        //hides loading screen
         //[HUD hide:YES];
         self.mapAlreadyLoaded = YES;

    }


    return annView;


}


return nil;

}

私が得る例外は次のとおりです。

*** Terminating app due to uncaught exception 'NSGenericException', 
reason: '*** Collection <__NSArrayM: 0x21683870> was mutated while being enumerated.'
*** First throw call stack:
(0x32dc62a3 0x3259897f 0x32dc5d85 0x37c4d33b 0x37c50373 0x86e63 0x37dcc67d 0x36e52311 0x36e521d8)

しかし、私が使用する場合:

[self populateMap];
//[self performSelectorInBackground:@selector(populateMap) withObject:nil];

アプリケーションは正常に動作します。

なぜこれが起こっているのですか?

4

1 に答える 1

0

これが発生する可能性のある理由はいくつかあります。エラーは、ある時点で、あなた(または基盤となるiOSライブラリ)が、そのプロセスの進行中に変更された配列を列挙しようとしたことを示しています。

populateMapメインスレッドをオフにすると機能し、セカンダリスレッドで呼び出すと機能しないという事実は、何らかの競合状態が発生していることを示しています。

すべてUIKitがスレッドセーフであるとは限らないことを覚えておいてください(ほとんどはそうではありません)-したがって、そこに問題がある可能性があります。バックグラウンドスレッドを使用したまま、マップに注釈を追加します。

[galleryListMap addAnnotation:addrAnnotation];

...これは、クラッシュが発生する行でもあります。MapViewに注釈を追加すると、おそらく現在のすべての注釈を繰り返して表示を更新するのは当然のことです。これらの呼び出しをバックグラウンドスレッドから行っているため、これにより多くの問題が発生する可能性があります。

代わりに、これを試してください:

[galleryListMap performSelectorOnMainThread:@selector(addAnnotation:)
                                 withObject:addrAnnotation 
                               waitUntilDone:YES]

これにより、マップビューでメインスレッドに注釈が追加されます。原則として、UIKitスレッドセーフなものはごくわずかです(アップルのドキュメントには完全なリストがあります)。

于 2012-10-12T15:02:07.697 に答える