2013-11-15 7 views
10

Ho un'app per visualizzare la mappa e l'annotazione personalizzata. La mia applicazione si arresta in modo anomalo quando l'utente tocca l'annotazione. Succede solo in iOS 7. Sta funzionando bene con iOS 6 e iOS 5.Blocco con selettore non riconosciuto quando l'utente tocca l'annotazione

Segue la relazione crash che viene visualizzato nella console:

ERROR: Trying to select an annotation which has not been added 
-[__NSSetM coordinate]: unrecognized selector sent to instance 0x18c9d580 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSetM coordinate]: unrecognized selector sent to instance 0x18c9d580' 
*** First throw call stack: 
(
    0 CoreFoundation      0x020415e4 __exceptionPreprocess + 180 
    1 libobjc.A.dylib      0x016918b6 objc_exception_throw + 44 
    2 CoreFoundation      0x020de903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275 
    3 CoreFoundation      0x0203190b ___forwarding___ + 1019 
    4 CoreFoundation      0x0206e46e __forwarding_prep_1___ + 14 
    5 MapKit        0x000de10c _Z21_insertionNodeForItemP11objc_objectP14MKQuadTrieNode + 50 
    6 MapKit        0x000de428 _Z9_containsP11objc_objectP14MKQuadTrieNode + 27 
    7 MapKit        0x000de8ed -[MKQuadTrie contains:] + 39 
    8 MapKit        0x000d4918 -[MKAnnotationManager selectAnnotation:animated:avoid:] + 116 
    9 MapKit        0x00090789 -[MKMapView handleTap:] + 541 
    10 UIKit        0x0056ae8c _UIGestureRecognizerSendActions + 230 
    11 UIKit        0x00569b00 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 383 
    12 UIKit        0x0056b56d -[UIGestureRecognizer _delayedUpdateGesture] + 60 
    13 UIKit        0x0056eacd ___UIGestureRecognizerUpdate_block_invoke + 57 
    14 UIKit        0x0056ea4e _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 317 
    15 UIKit        0x00565148 _UIGestureRecognizerUpdate + 199 
    16 CoreFoundation      0x020094ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30 
    17 CoreFoundation      0x0200941f __CFRunLoopDoObservers + 399 
    18 CoreFoundation      0x01fe7344 __CFRunLoopRun + 1076 
    19 CoreFoundation      0x01fe6ac3 CFRunLoopRunSpecific + 467 
    20 CoreFoundation      0x01fe68db CFRunLoopRunInMode + 123 
    21 GraphicsServices     0x01f6c9e2 GSEventRunModal + 192 
    22 GraphicsServices     0x01f6c809 GSEventRun + 104 
    23 UIKit        0x001f2d3b UIApplicationMain + 1225 
    24 CustomMKAnnotationView    0x0000285a main + 170 
    25 CustomMKAnnotationView    0x000027a5 start + 53 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

E mi hanno creato codice nella seguente maniera:

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view 
{ 
    if ([view.annotation isKindOfClass:[BasicMapAnnotation class]]) 
     { 
     if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&& 
      _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude) 
     { 
      return; 
     } 
     if (_calloutAnnotation) 
     { 
      [mapView removeAnnotation:_calloutAnnotation]; 
      _calloutAnnotation = nil; 
     } 
     _calloutAnnotation = [[[CalloutMapAnnotation alloc] 
           initWithLatitude:view.annotation.coordinate.latitude 
           andLongitude:view.annotation.coordinate.longitude]autorelease]; 
     [mapView addAnnotation:_calloutAnnotation]; 

     [mapView setCenterCoordinate:_calloutAnnotation.coordinate animated:YES]; 
    }else 
    { 
     if([delegate respondsToSelector:@selector(customMKMapViewDidSelectedWithInfo:)]) 
     { 
      [delegate customMKMapViewDidSelectedWithInfo:@"Annotation clicked"]; 
     } 
    } 
} 

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view 
    { 
    if (_calloutAnnotation&& ![view isKindOfClass:[CallOutAnnotationVifew class]]) 
    { 
     if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&& 
      _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude) 
     { 
      [mapView removeAnnotation:_calloutAnnotation]; 
      _calloutAnnotation = nil; 
     } 
    } 
} 

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation 
{ 
    if ([annotation isKindOfClass:[CalloutMapAnnotation class]]) 
    { 

     CallOutAnnotationVifew *annotationView = (CallOutAnnotationVifew *)[mapView  dequeueReusableAnnotationViewWithIdentifier:@"CalloutView"]; 
     if (!annotationView) 
     { 
      annotationView = [[[CallOutAnnotationVifew alloc] initWithAnnotation:annotation reuseIdentifier:@"CalloutView"] autorelease]; 
      JingDianMapCell *cell = [[[NSBundle mainBundle] loadNibNamed:@"JingDianMapCell" owner:self options:nil] objectAtIndex:0]; 
      cell.titleLable.text = @"Testing"; 
      [annotationView.contentView addSubview:cell]; 

     } 
     return annotationView; 
    }else if ([annotation isKindOfClass:[BasicMapAnnotation class]]) 
    { 

     MKAnnotationView *annotationView =[self.mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomAnnotation"]; 
     if (!annotationView) 
     { 
      annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation 
                  reuseIdentifier:@"CustomAnnotation"] autorelease]; 
      annotationView.canShowCallout = NO; 
      annotationView.image = [UIImage imageNamed:@"pin.png"]; 
     } 

     return annotationView; 
    } 
    return nil; 
} 

In didSelectAnnotationView e didDeselectAnnotationView Aggiungo la nuova vista di annotazione e rimuovo la vecchia vista di annotazione. La visualizzazione delle annotazioni è una classe personalizzata. E _calloutAnnotation è un oggetto di CalloutMapAnnotation che è una classe NSObject per l'aggiunta di annotazioni.

+0

Per cosa viene utilizzato '_calloutAnnotation'? Stai chiamando 'selectAnnotation' nella tua app? In inglese semplice, qual è il codice in didSelectAnnotationView e didDeselectAnnotationView che cerca di fare (aggiungere una spiegazione alla domanda se la risposta è lunga). – Anna

+0

L'app chiama callAnnotation ovunque? Assicurati che selectAnnotation sia chiamato _after_ l'annotazione sia stata aggiunta. Sembra che _calloutAnnotation o qualche altra variabile di annotazione sia referenziata quando contiene un riferimento non valido (non un ID ). – Anna

risposta

1

_calloutAnnotation non contiene la vista di annotazione. Penso che tu abbia un codice come questo @prorerty (weak, nonatomic) MKAnnotation * calloutAnnotation; cambiare weak a strong dovrebbe aiutare.

0

Il tuo problema è qui:

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view 
    { 
    if (_calloutAnnotation&& ![view isKindOfClass:[CallOutAnnotationVifew class]]) 
    { 
     if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&& 
      _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude) 
     { 
      [mapView removeAnnotation:_calloutAnnotation]; 
//EDIT: This code is broken don't use it :) 
      //in iOS7.0 responder chain is changed a bit and you can't call this directly give it some time or remove this line and your crash will be gone ;) 
//   double delayInSeconds = 0.5; 
//  dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
//  dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
//   _calloutAnnotation = nil; 
//  }); 
     } 
    } 
} 
+0

Per evitare possibili condizioni di gara, suggerirei di non disperdere dopo un timeout. Quanto segue dovrebbe funzionare altrettanto bene: 'dispatch_async (dispatch_get_main_queue(),^{self.calloutAnnotation = nil;});' or '[self performSelectorOnMainThread: @selector (setCalloutAnnotation :) withObject: nil waitUntilDone: NO];' in entrambi caso l'azione sarà fatta sul thread principale ogni volta che si libera. Inoltre, questo è ancora solo un rimedio e non cancella il messaggio "ERRORE ..." della console. – user3099609

1

Marcin è parzialmente ragione. Tuttavia l'ultimo indizio si trova in ERROR: Trying to select an annotation which has not been added Ciò che sta accadendo qui è che l'utente tocca una "bolla di callout" che è in realtà una vista di annotazione. Come parte di ciò, MapView dapprima deseleziona l'annotazione attualmente selezionata e quindi seleziona l'annotazione che l'utente ha sfruttato. Tuttavia, dal momento che hai già rimosso l'annotazione da selezionare dalla mappa nel passaggio di deselezione, non c'è nulla da selezionare. Da qui il messaggio "ERRORE ..." nel debugger.

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view 
{ 
    if (_calloutAnnotation&& ![view isKindOfClass:[CallOutAnnotationVifew class]]) 
    { 
    if (_calloutAnnotation.coordinate.latitude == view.annotation.coordinate.latitude&& 
     _calloutAnnotation.coordinate.longitude == view.annotation.coordinate.longitude) 
    { 
     CalloutMapAnnotation *oldAnnotation = self.calloutAnnotation; //saving it to be removed from the map later 
     self.calloutAnnotation = nil; //setting to nil to know that we aren't showing a callout anymore 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [mapView removeAnnotation:oldAnnotation]; //removing the annotation a bit later 
     }); 
    } 
    } 
} 
+0

Sì, hai ragione. Questo è un modo più pulito e sicuro per affrontare questo. Il mio codice ha un bug di impatto che può finire con più annotazioni selezionate. –

Problemi correlati