2012-12-04 4 views
3

좌표를 기준으로 MKPolygon 초로 MKMapView을 만들었습니다. 지도에 여러 개의 다각형이 있습니다 (응용 프로그램으로 다시 작성하는 예는 here을 참조하십시오).MKPolygon ontouch detailview

사용자가 다각형을 만졌을 때 위치에 대한 정보가 포함 된 팝업보기가 열립니다. 이 정보는 현재 좌표와 함께 plist 파일 안에 저장됩니다.

지금까지 내가 터치 이벤트를 얻고 로그에 다각형을 만졌을 때 인쇄 할 수 있습니다.

I가 가지고있는 질문 :
MKPolygonView 사용자가 핀 자세한 내용은 도청이 현재 위치에 대한 팝업 번 MKAnnotationView처럼 사용할 수 있습니까?

다각형보기에서도 동일한 작업을 수행하려고합니다. 만졌을 때, 사용자는 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]; 
[email protected]"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 
+1

의 새로운 기능 : 마지막으로

//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에서와 같이 동일한 방법을 사용 특정 질문? 히트 감지가 작동합니까? – Anna

+2

주석과 마찬가지로 내장 된 설명 선보기가 없습니다. 사용자 정의 UIView를 만들고 addSubview 또는 사용자 정의 UIViewController를 수행하고 present/push해야합니다. – Anna

+0

아. 고맙습니다. 나는 어제이 사실에 대해 좌절했기 때문에 나는 진짜 질문을하는 것을 잊었다. 폐쇄 된 상태에서도 1 + 당신을 위해. – Dwill

답변

3

불행하게도, 오버레이를 들면, 없다 아무 내장 된 터치 감지 및 콜 아웃 뷰 주석에 대한이 같은.

이미 터치 감지를 수동으로 수행해야합니다 (작동하는 것처럼 보입니다).
(더욱 불행한 여기 오버레이보기로 직접 제스처 인식기를 추가하는 작동하지 않는다는 것입니다 -. 당신이 전체지도에 추가 한 후 터치 포인트가 어떤 오버레이에 있는지 여부를 확인해야합니다)

오버레이 콜 아웃보기의 경우 오버레이에서 터치가 감지되면 UIView 사용자 지정을 만들고 addSubview을 수행 할 수 있습니다. 오버레이보기 대신 맵에 추가하는 것이 좋으며 사용자 정의 콜 아웃보기의 프레임을 결정하기 위해 이미 계산중인 CGPoint point을 사용할 수 있습니다.

다른 오버레이에 대한 콜 아웃이 이미 표시된 상태에서 다른 오버레이에서 탭하면 쉽게 제거하고 다시 추가 할 수 있도록 오버레이 콜 아웃보기에 대한 ivar/속성 참조를 유지해야 할 수도 있습니다.

아마도 더 쉬운 또 다른 옵션은 사용자 정의 UIViewController을 작성하여 제시하거나 누르는 것입니다. 표시 세부 사항은 네비게이션 컨트롤러 및/또는 스토리 보드 사용 여부에 따라 다릅니다.

앱이 iPad 용으로 제작 된 경우 UIPopoverController을 사용하여 '설명 문구'를 표시 할 수도 있습니다.
코드 예는 How do I display a UIPopoverView as a annotation to the map view? (iPad)을 참조하십시오 (주석이 있지만 오버레이에 적용 할 수 있어야합니다).


어떤 오버레이를 탭했는지 확인한 후에는 원본 데이터 소스 ( outages 어레이)에있는 관련 데이터를 표시해야합니다. 현재 오버레이가 생성되고 추가되지만 원본 데이터 객체 (참조 번호 outages 어레이의 중단 사전)는 다시 참조되지 않습니다.

는 (사용자 지정 속성 has issues and workarounds을 추가 MKPolygon 하위 클래스와 완전히 사용자 정의 MKOverlay 클래스는 다른 추가 작업을 많이 소개 생성.) 현재 데이터 소스 구조에 대한

, 간단하고 빠른 (다소 원유) 옵션을 오버레이와 연결된 중단 객체 배열의 속성을 outages 색인의 색인에 설정하는 것입니다. 당신이 test를 사용하는 것처럼 (정전 개체에서 오는)

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

viewForOverlay에서 보이는 다음 title 속성이 NSString하고 배열 인덱스가 정수이기 때문에, 우리는 문자열로 변환 할 수 있습니다 다각형의 색을 결정합니다. 외부에서 선언/설정 한 test 변수의 값은 overlay과 반드시 ​​일치하지 않을 수 있습니다 (현재지도를 추가하는 순서가 아니라 동일한 오버레이에 대해 viewForOverlay을 여러 번 호출 할 수 있음). overlay 매개 변수의 일부 등록 정보를 기반으로 정전 오브젝트를 검색해야합니다. 우리는 정전의 인덱스에 오버레이의 title 속성을 설정하고 있기 때문에 :

if (mapCoordinateIsInPolygon) { 
    int outageIndex = [overlay.title intValue]; 
    NSDictionary *outageDict = [outages objectAtIndex:outageIndex]; 
    NSLog(@"hit, outageDict = %@", outageDict); 
    //show view with info from outageDict... 
} 
+0

안녕하세요 Anna, 위의 코드에서보기와 하위보기를 구현하는 방법에 대한 예를 들어 주시겠습니까? 사전에서 출력을 NSLog로 시도했지만 마지막 레코드 만 표시합니다. – Dwill

+0

시도한 정확한 NSLog는 무엇입니까? 문제는 오버레이가 어떤 중단에 대한 것인지 알 수있는 방법이 없다는 것입니다. 정지 배열에서 각 객체에는 고유 한 문자열 ID가 연관되어 있습니까? 오버레이의 '제목'을 해당 고유 한 문자열로 설정 한 다음 나중에 해당 ID와 관련된 중단 개체를 찾을 수 있습니다. – Anna

+0

네, 그게 제가 가지고있는 문제입니다. 각 정전과 관련된 정전 번호가 있지만 정전이 무엇인지 알 수있는 방법이 없습니다. 내가해야 할 일의 예를 들려 주시겠습니까? – Dwill