3

座標に基づいてsをMKMapView使用して作成しました。MKPolygonマップ上に複数のポリゴンがあります(アプリとして再作成しているものの例については、こちらをご覧ください)。

私がやろうとしているのは、ユーザーがポリゴンに触れると、場所に関する情報を含むポップオーバービューが開くことです。この情報は現在、座標とともにplistファイル内に保存されています。

これまでのところ、タッチイベントを取得して、ポリゴンがタッチされたことをログに出力できるようになっています。

私が持っている質問は次のとおりです。ユーザーがピンをタップすると、その現在の場所に関するより多くの情報がポップアップする場所のように使用
できますか?MKPolygonViewMKAnnotationView

ポリゴンビューでも同じことをしたいと思います。タッチすると、plistに保存されている場所に関する詳細情報が表示されます。可能であれば、それを機能させるための最良の方法は何でしょうか?

私の現在のコードは以下の通りです。

#import "outagemapViewController.h"
#import "MyAnnotation.h"
#import "WildcardGestureRecognizer.h"
#define METERS_PER_MILE 46309.344
@interface outagemapViewController ()

@end

@implementation outagemapViewController
- (void)viewDidLoad {

outages = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"outages"ofType:@"plist"]];


for (NSDictionary *coloredAreas in outages) {
   coordinateData = coloredAreas[@"coords"];
test = coloredAreas[@"outages"];

    NSLog(@"test %@", test);
    coordsLen = [coordinateData count];
      NSLog(@"coords %d", coordsLen);
    CLLocationCoordinate2D coords[coordsLen];
    for (i=0; i < coordsLen; i++) {
        NSString *lat = coordinateData[i];
        NSArray *latt = [lat componentsSeparatedByString:@","];
        double latitude = [[latt objectAtIndex:0] doubleValue];
        double longitude = [[latt objectAtIndex:1] doubleValue];
       coords[i] = CLLocationCoordinate2DMake(latitude, longitude);

    }


 MKPolygon* poly2 = [MKPolygon polygonWithCoordinates:coords count:coordsLen];
 poly2.title=@"test";
 [self.mapView addOverlay:poly2];
 }
 }
 - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
{
    if ([overlay isKindOfClass:[MKPolygon class]])
    {

        MKPolygonView*    aView = [[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay];

        int numbers = [test intValue];

        if(numbers >= 10){
            aView.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.6];
            aView.strokeColor = [[UIColor greenColor] colorWithAlphaComponent:1.0];
            aView.lineWidth = 3;
        }else if(numbers < 10){
            aView.fillColor = [[UIColor yellowColor] colorWithAlphaComponent:0.6];
            aView.strokeColor = [[UIColor yellowColor] colorWithAlphaComponent:1.0];
            aView.lineWidth = 3;

                    }

        return aView;
    }


    return nil;
}
 }

-(void)viewWillAppear:(BOOL)animated{
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 35.20418;
zoomLocation.longitude = -89.86862;

MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation,         0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);

[_mapView setRegion:viewRegion animated:YES];

WildcardGestureRecognizer * tapInterceptor = [[WildcardGestureRecognizer alloc] init];
tapInterceptor.touchesBeganCallback = ^(NSSet * touches, UIEvent * event) {
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self.mapView];

    CLLocationCoordinate2D coord = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
    MKMapPoint mapPoint = MKMapPointForCoordinate(coord);
    for (id overlay in self.mapView.overlays)
    {
        if ([overlay isKindOfClass:[MKPolygon class]])
        {
            MKPolygon *poly = (MKPolygon*) overlay;
            id view = [self.mapView viewForOverlay:poly];
            if ([view isKindOfClass:[MKPolygonView class]])
            {
                MKPolygonView *polyView = (MKPolygonView*) view;
                CGPoint polygonViewPoint = [polyView pointForMapPoint:mapPoint];
                BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polyView.path, NULL, polygonViewPoint, NO);
                if (mapCoordinateIsInPolygon) {
                   // debug(@"hit!");
                    NSLog(@"hit");
                } else {
                     NSLog(@"miss");
                }
            }
        }
    }

};
[self.mapView addGestureRecognizer:tapInterceptor];
}

- (void)didReceiveMemoryWarning
{
 [super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end
4

1 に答える 1

3

残念ながら、オーバーレイの場合、注釈の場合のような組み込みのタッチ検出およびコールアウトビューはありません。

すでに行っているように、手動でタッチ検出を行う必要があります(そして、それは機能するはずです)。
(ここでさらに不幸なのは、ジェスチャレコグナイザーをオーバーレイビューに直接追加しても機能しないことです。マップ全体に追加してから、タッチポイントがオーバーレイにあるかどうかを確認する必要があります。)

オーバーレイコールアウトビューの場合、オーバーレイのタッチを検出したら、カスタムUIViewを作成して実行できますaddSubview。オーバーレイビューの代わりにマップに追加することをお勧めしCGPoint pointます。すでに計算しているものを使用して、カスタムコールアウトビューのフレームを決定できる場合があります。

また、オーバーレイコールアウトビューへのivar / property参照を保持して、別のオーバーレイのコールアウトがすでに表示されているときにユーザーが別のオーバーレイをタップした場合に簡単に削除および再追加できるようにすることもできます。

おそらく簡単なもう1つのオプションは、カスタムを作成してUIViewController表示またはプッシュすることです。表示の詳細は、ナビゲーションコントローラーやストーリーボードを使用しているかどうかによって異なります。

アプリがiPad用にも構築されている場合は、を使用して「コールアウト」を表示することもできますUIPopoverControllerマップビューへの注釈としてUIPopoverViewを表示するにはどうすればよいですか?を
参照してください。(iPad)コード例(注釈付きですが、オーバーレイに適合させることができるはずです)。


タップされたオーバーレイを特定したら、元のデータソース(outages配列)にある関連データを表示する必要があります。現在、オーバーレイが作成および追加されていますが、元のデータオブジェクト(outagesアレイ内の停止ディクショナリ)への参照はありません。

MKPolygon(カスタムプロパティを追加するためのサブクラス化には問題と回避策があり、完全にカスタムMKOverlayクラスを作成すると、他の多くの追加作業が発生します。)

現在のデータソース構造の場合、単純で迅速な(そしてやや大雑把な)オプションは、オーバーレイのtitleプロパティをoutages、オーバーレイに関連付けられた停止オブジェクトの配列のインデックスに設定することです。titleプロパティはanであり、配列インデックスは整数であるためNSString、文字列に変換します。

NSUInteger outageIndex = [outages indexOfObject:coloredAreas];
poly2.title = [NSString stringWithFormat:@"%d", outageIndex];
[self.mapView addOverlay:poly2];

では、ポリゴンの色を決定するために(停止オブジェクトに由来する)をviewForOverlay使用しているように見えます。test外部で宣言/設定されたtest変数の値は、現在呼び出されているデリゲートメソッドと必ずしも同期していませんoverlay(マップは同じオーバーレイに対して複数回呼び出すことができviewForOverlay、必ずしも追加した順序で呼び出す必要はありません)。パラメータのプロパティに基づいて、停止オブジェクトを取得する必要がありoverlayます。オーバーレイのtitleプロパティを停止のインデックスに設定しているため、次のようになります。

//int numbers = [test intValue];  <-- remove this line

int outageIndex = [overlay.title intValue];
NSDictionary *outageDict = [outages objectAtIndex:outageIndex];
id outageNumbersObject = outageDict[@"outages"]; 
//replace id above with actual type
//can't tell from code in question whether it's NSString or NSNumber 
int numbers = [outageNumbersObject intValue];

//use "numbers" to set polygon color...

最後に、オーバーレイをタップするときは、と同じメソッドを使用しviewForOverlayて停止オブジェクトを取得します。

if (mapCoordinateIsInPolygon) {
    int outageIndex = [overlay.title intValue];
    NSDictionary *outageDict = [outages objectAtIndex:outageIndex];
    NSLog(@"hit, outageDict = %@", outageDict);
    //show view with info from outageDict...
} 
于 2012-12-05T16:04:01.400 に答える