2013-11-15 7 views
10

マップとカスタムアノテーションを表示するアプリがあります。ユーザーが注釈をタッチすると、アプリケーションがクラッシュします。 iOS 7でのみ発生します。これは、5ユーザーがアノテーションに触れると認識できないセレクタがクラッシュする

後はコンソールに表示されてクラッシュレポートでのiOS 6とiOSで細かい作業だ:

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 

そして、私は次のようにコードを作成しました:で

-(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; 
} 

didSelectAnnotationViewおよびdidDeselectAnnotationView私は新しい注釈ビューを追加し、古い注釈ビューを削除します。注釈ビューはカスタムクラスです。 _calloutAnnotationは、追加注釈のNSObjectクラスであるCalloutMapAnnotationのオブジェクトです。

+0

「_calloutAnnotation」は何に使用されていますか?あなたのアプリで 'selectAnnotation'を呼び出していますか?普通の英語で、didSelectAnnotationViewとdidDeselectAnnotationViewのコードは何ですか?答えが長い場合は質問に説明を追加してください。 – Anna

+0

アプリはどこでもselectAnnotationを呼び出していますか?注釈が追加されてからselectAnnotationが呼び出されていることを確認してください。 _calloutAnnotationやその他の注釈変数が、無効な参照(id ではなく)を含んでいるときに参照されているようです。 – Anna

答えて

1

_calloutAnnotationには注釈ビューが含まれていません。私はあなたのコードが@prorerty (weak, nonatomic) MKAnnotation * calloutAnnotation;のようにweakからstrongに変わるのを助けるべきだと思います。

0

あなたの問題はここにある:

-(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

競合状態を回避するために、タイムアウト後にディスパッチすることを推奨します。次のようにも動作します: 'dispatch_async(dispatch_get_main_queue()、^ {self.calloutAnnotation = nil;});'または 'self performSelectorOnMainThread:@selector(setCalloutAnnotation :) withObject:nil waitUntilDone:NO];'メインスレッドが解放されるたびにアクションがメインスレッド上で実行されます。また、これはまだ回避策であり、コンソール "ERROR ..."メッセージをクリアしません。 – user3099609

1

マルチンは、部分的に正しいです。しかし、究極の手がかりがあるERROR: Trying to select an annotation which has not been added ここで起こっているのは、ユーザーが実際に注釈ビューである「コールアウトバブル」をタップすることです。その一環として、MapViewはまず現在選択されている注釈の選択を解除してから、ユーザがタップした注釈を選択します。 しかし、選択解除のステップで既に選択されている注釈をマップから削除しているため、選択するものはありません。したがって、デバッガの "ERROR ..."というメッセージが表示されます。

-(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

はい、あなたは正しいです。これはこれに対処するよりクリーンで安全な方法です。私のコードには複数の選択された注釈で終わるかもしれないインパクトバグがあります。 –

関連する問題