2012-11-21 8 views
5

私はMKCircleを使用して特定のユーザーアクションの半径情報を表示するmapviewを持っています。ピンと注釈の接触を無視して、マップするためにタッチジェスチャーを追加するにはどうすればよいですか?

私がしたいことは、ユーザーが地図に触れるとMKCircleを却下できるようにすることです。しかし、MKCircleは、ユーザーが他のピンまたはMKCircleのいずれかに触れると却下しないようにしたいと思います。

アイデア?

はここに私の現在のマップのどの部分がタッチされMKCircle退けコード、次のとおりです。deactivateAllRadars方法で

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(deactivateAllRadars)]; 
[tap setCancelsTouchesInView:NO]; 
[_mapView addGestureRecognizer:tap]; 

答えて

5

、あなたはMKAnnotationViewがタップされているか否かを伝えるためにhitTest:withEvent:を使用することができます。

この例は、How can I catch tap on MapView and then pass it to default gesture recognizers?(2番目のコードサンプル)に示されています。

注釈がタップされている場合は、これで円を削除しないようにします。

注釈がタップされていない場合は、MKCircleがタップされているかどうかを確認して(例ではHow to capture Tap gesture on MKMapViewを参照)、タッチからサークルの中心までの距離がその半径。

deactivateAllRadarsは、関連付けられたジェスチャ認識プログラムからの情報が必要となるため、deactivateAllRadars:(UITapGestureRecognizer *)tgrに変更する必要があります。 + init tapをallocするメソッドのセレクタの最後にもコロンを追加してください。例えば

:あなたはのように直接を比較することはできませんので

func didTapOnMap(recognizer: UITapGestureRecognizer) { 
    let tapLocation = recognizer.locationInView(self) 
    if let subview = self.hitTest(tapLocation, withEvent: nil) { 
     if subview.isKindOfClass(NSClassFromString("MKNewAnnotationContainerView")!) { 
      print("Tapped out") 
     } 
    } 
} 

MKNewAnnotationContainerViewは、民間の内部クラスです:

-(void)deactivateAllRadars:(UITapGestureRecognizer *)tgr 
{ 
    CGPoint p = [tgr locationInView:mapView]; 

    UIView *v = [mapView hitTest:p withEvent:nil]; 

    id<MKAnnotation> ann = nil; 

    if ([v isKindOfClass:[MKAnnotationView class]]) 
    { 
     //annotation view was tapped, select it... 
     ann = ((MKAnnotationView *)v).annotation; 
     [mapView selectAnnotation:ann animated:YES]; 
    } 
    else 
    { 
     //annotation view was not tapped, deselect if some ann is selected... 
     if (mapView.selectedAnnotations.count != 0) 
     { 
      ann = [mapView.selectedAnnotations objectAtIndex:0]; 
      [mapView deselectAnnotation:ann animated:YES]; 
     } 


     //remove circle overlay if it was not tapped...   
     if (mapView.overlays.count > 0) 
     { 
      CGPoint touchPoint = [tgr locationInView:mapView]; 

      CLLocationCoordinate2D touchMapCoordinate 
       = [mapView convertPoint:touchPoint toCoordinateFromView:mapView]; 

      CLLocation *touchLocation = [[CLLocation alloc] 
       initWithLatitude:touchMapCoordinate.latitude 
       longitude:touchMapCoordinate.longitude]; 

      CLLocation *circleLocation = [[CLLocation alloc] 
       initWithLatitude:circleCenterLatitude 
       longitude:circleCenterLongitude]; 

      CLLocationDistance distFromCircleCenter 
       = [touchLocation distanceFromLocation:circleLocation]; 

      if (distFromCircleCenter > circleRadius) 
      { 
       //tap was outside the circle, call removeOverlay... 
      } 
     } 
    } 
} 
+0

完璧に動作します! – JimmyJammed

+0

iOS 7では動作しません。ヒットテストではMKNewAnnotationContainerViewが返されます。どのようにそれを修正するための任意のアイデア? –

+0

@RodrigoRuiz、MKNewAnnotationContainerView(プライベートクラス)は、この特定のコードが気にしない地図領域をタップすると返されるものです。注釈をタップすると、iOS 7はまだコードがチェックしているものであるMKAnnotationView(文書化されたクラス)を返します。それでも問題がある場合は、新しい質問を詳細で開始してください。 – Anna

3

これは私のスウィフト2.1互換性のあるバージョンである

if subview is MKNewAnnotationContainerView { 
} 
+0

これに遅れていますが、 "private inner class"と言うと、これは文字通り、これが別のクラス(おそらくMKAnnotationView)の内部にあるプライベートクラスであることを意味しますか? – Dallas

+0

あなたは正しく、「内部」は誤解を招く:私はMKNewAnnotationContainerViewがどこに定義されているか分かりませんが、それは確かにプライベートです。ドキュメントを見つけた場合は、自由に回答を更新してください! –

関連する問題