[ios] MKMapView가 드래그 / 이동되었는지 확인

MKMapView가 드래그되었는지 확인하는 방법이 있습니까?

사용자가 사용하여지도를 끌 때마다 중심 위치를 얻고 싶지만 사용자가지도를 CLLocationCoordinate2D centre = [locationMap centerCoordinate];탐색하자마자 실행되는 델리게이트 메서드 또는 무언가가 필요합니다.

미리 감사드립니다



답변

상기 봐 MKMapViewDelegate의 참조입니다.

특히 다음 방법이 유용 할 수 있습니다.

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated

해당 메서드가 호출되도록 맵 뷰의 대리자 속성이 설정되어 있는지 확인합니다.


답변

어떤 이유로 든 지역이 변경되면 수락 된 답변의 코드가 실행됩니다. 지도 끌기를 제대로 감지하려면 UIPanGestureRecognizer를 추가해야합니다. Btw, 이것은 드래그 제스처 인식기입니다 (패닝 = 드래그).

1 단계 : viewDidLoad에 제스처 인식기 추가 :

-(void) viewDidLoad {
    [super viewDidLoad];
    UIPanGestureRecognizer* panRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didDragMap:)];
    [panRec setDelegate:self];
    [self.mapView addGestureRecognizer:panRec];
}

2 단계 : UIGestureRecognizerDelegate 프로토콜을 뷰 컨트롤러에 추가하여 델리게이트로 작동합니다.

@interface MapVC : UIViewController <UIGestureRecognizerDelegate, ...>

3 단계 : UIPanGestureRecognizer가 MKMapView의 기존 제스처 인식기와 함께 작동하도록 다음 코드를 추가합니다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

4 단계 : 메서드를 드래그 당 50 번 대신 한 번 호출하려는 경우 선택기에서 “드래그 종료”상태를 감지합니다.

- (void)didDragMap:(UIGestureRecognizer*)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateEnded){
        NSLog(@"drag ended");
    }
}


답변

이것은 사용자가 시작한 확대 / 축소 변경과 이동을 감지하는 유일한 방법입니다.

- (BOOL)mapViewRegionDidChangeFromUserInteraction
{
    UIView *view = self.mapView.subviews.firstObject;
    //  Look through gesture recognizers to determine whether this region change is from user interaction
    for(UIGestureRecognizer *recognizer in view.gestureRecognizers) {
        if(recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateEnded) {
            return YES;
        }
    }

    return NO;
}

static BOOL mapChangedFromUserInteraction = NO;

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    mapChangedFromUserInteraction = [self mapViewRegionDidChangeFromUserInteraction];

    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}


답변

(그냥) @mobi의 탁월한 솔루션의 Swift 버전 :

private var mapChangedFromUserInteraction = false

private func mapViewRegionDidChangeFromUserInteraction() -> Bool {
    let view = self.mapView.subviews[0]
    //  Look through gesture recognizers to determine whether this region change is from user interaction
    if let gestureRecognizers = view.gestureRecognizers {
        for recognizer in gestureRecognizers {
            if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {
                return true
            }
        }
    }
    return false
}

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}


답변

의 Jano의 답변에 대한 Swift 3 솔루션 :

ViewController에 프로토콜 UIGestureRecognizerDelegate 추가

class MyViewController: UIViewController, UIGestureRecognizerDelegate

에서 UIPanGestureRecognizer를 viewDidLoad만들고 delegateself로 설정 합니다.

viewDidLoad() {
    // add pan gesture to detect when the map moves
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.didDragMap(_:)))

    // make your class the delegate of the pan gesture
    panGesture.delegate = self

    // add the gesture to the mapView
    mapView.addGestureRecognizer(panGesture)
}

제스처 인식기가 기존 MKMapView 제스처와 함께 작동하도록 프로토콜 메서드를 추가합니다.

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

이동 제스처에서 선택기가 호출 할 메서드를 추가합니다.

func didDragMap(_ sender: UIGestureRecognizer) {
    if sender.state == .ended {

        // do something here

    }
}


답변

내 경험상 “입력하는 동안 검색”과 유사하게 타이머가 가장 신뢰할 수있는 솔루션이라는 것을 알았습니다. 이동, 집기, 회전, 두드리기, 두 번 두드리기 등을위한 제스처 인식기를 추가 할 필요가 없습니다.

해결책은 간단합니다.

  1. 지도 지역이 변경되면 타이머 설정 / 초기화
  2. 타이머가 실행되면 새 지역의 마커를로드합니다.

    import MapKit
    
    class MyViewController: MKMapViewDelegate {
    
        @IBOutlet var mapView: MKMapView!
        var mapRegionTimer: NSTimer?
    
        // MARK: MapView delegate
    
        func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            setMapRegionTimer()
        }
    
        func setMapRegionTimer() {
            mapRegionTimer?.invalidate()
            // Configure delay as bet fits your application
            mapRegionTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "mapRegionTimerFired:", userInfo: nil, repeats: false)
        }
    
        func mapRegionTimerFired(sender: AnyObject) {
            // Load markers for current region:
            //   mapView.centerCoordinate or mapView.region
        }
    
    }
    


답변

또 다른 가능한 해결책은 다음과 같이지도보기를 보유하는보기 컨트롤러에서 touchesMoved : (또는 touchesEnded : 등)를 구현하는 것입니다.

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];

    for (UITouch * touch in touches) {
        CGPoint loc = [touch locationInView:self.mapView];
        if ([self.mapView pointInside:loc withEvent:event]) {
            #do whatever you need to do
            break;
        }
    }
}

경우에 따라 제스처 인식기를 사용하는 것보다 더 간단 할 수 있습니다.