2014-06-12 3 views
5

사용자 지정 호출을 표시하는 MKPinAnnotationView의 사용자 지정 하위 클래스가 있습니다. 해당 주석 내부에서 터치 이벤트를 처리하려고합니다.MKMapView 변경 선택 방지 (깔끔하게)

나는 (아래) 실제 해결책이 있지만 그냥 옳다고 생각하지 않습니다. 나는 어둠의 법칙을 가지고 있는데, 언제든지 performSelector: .. withDelay:을 사용할 때마다 나는 그 시스템을 다루기보다는 싸우고있다.

누구든지 MKMapView 및 주석 선택 처리의 공격적인 이벤트 처리에 대한 좋은, 깨끗한 해결 방법이 있습니까?

나의 현재 솔루션 :

내 제스처 recognisers가지도보기로 실행되지 않는이없이 (내 자신의 히트 테스트를 (내 모든 주석 선택 클래스 코드)

는 이벤트를 소비 :

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event; { 
    // To enable our gesture recogniser to fire. we have to hit test and return the correct view for events inside the callout. 

    UIView* hitView = nil; 

    if (self.selected) { 
     // check if we tpped inside the custom view 
     if (CGRectContainsPoint(self.customView.frame, point)) 
      hitView = self.customView; 
    } 

    if(hitView) { 
     // If we are performing a gesture recogniser (and hence want to consume the action) 
     // we need to turn off selections for the annotation temporarily 
     // the are re-enabled in the gesture recogniser. 
     self.selectionEnabled = NO; 

     // *1* The re-enable selection a moment later 
     [self performSelector:@selector(enableAnnotationSelection) withObject:nil afterDelay:kAnnotationSelectionDelay]; 

    } else { 
     // We didn't hit test so pass up the chain. 
     hitView = [super hitTest:point withEvent:event]; 
    } 

    return hitView; 
} 

나의 setSelected를 오버라이드 (override)에서 나는 선택 해제를 무시할 수 있도록 나는 또한 선택을 해제 참고

0.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated; { 
    // If we have hit tested positive for one of our views with a gesture recogniser, temporarily 
    // disable selections through _selectionEnabled 
    if(!_selectionEnabled){ 
     // Note that from here one, we are out of sync with the enclosing map view 
     // we're just displaying out callout even though it thinks we've been deselected 
     return; 
    } 

    if(selected) { 
     // deleted code to set up view here 
     [self addSubview:_customView]; 

     _mainTapGestureRecogniser = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(calloutTapped:)]; 
     [_customView addGestureRecognizer: _mainTapGestureRecogniser]; 

    } else { 
     self.selected = NO; 
     [_customView removeFromSuperview]; 
    } 


} 

내가 싫어하는 라인이 인데, 쎄타가 늦어 져서 꽤 털이 난다. 슈퍼 뷰 체인을 뒤로 걸어 와서 mapView에 가야 선택이 여전히 가능하다는 것을 확신 할 수 있습니다.

-(MKMapView*)findMapView; { 
    UIView* view = [self superview]; 
    while(!_mapView) { 
     if([view isKindOfClass:[MKMapView class]]) { 
      _mapView = (MKMapView*)view; 
     } else if ([view isKindOfClass:[UIWindow class]]){ 
      return nil; 
     } else{ 
      view = [view superview]; 
      if(!view) 
       return nil; 
     } 
    } 

    return _mapView; 
} 

// Locate the mapview so that we can ensure it has the correct annotation selection state after we have ignored selections. 
- (void)enableAnnotationSelection { 
    // This reenables the seelction state and resets the parent map view's idea of the 
    // correct selection i.e. us. 
    MKMapView* map = [self findMapView]; 
    [map selectAnnotation:self.annotation animated:NO]; 
    _selectionEnabled = YES; 

} 

이 모든없이 단점 (나는 다른 솔루션에서 본 적이 플리커처럼 작동하는 것 같다. 그것은 상대적으로 간단합니다하지만 잘 생각하지 않습니다.

사람

답변

1

지도보기의 선택 추적 기능을 사용하지 않고 원숭이가 될 필요는 없다고 생각합니다. 원하는 것을 정확하게 해석한다면, hitTest:withEvent: 무시하고 canShowCalloutNO으로 설정하면됩니다. setSelected:에 따라 설명 문구/실종 애니메이션을 적절하게 수행하십시오. setHighlighted:을 재정의하고 표시되는 경우 사용자 정의 설명 선 표시를 조정해야합니다.