Поддерживать координату центра при защемлении MKMapView

Если вы щелкаете для увеличения/уменьшения масштаба в приложении Apple Maps при отслеживании местоположения устройства, компонент "панорамирования" жесты щепотка игнорируется, а синий индикатор положения остается фиксированным в центре экрана. Это не тот случай, когда используется простой MKMapView.

Предполагая, что у меня уже есть местоположение пользователя, как я могу добиться этого эффекта? Я попытался сбросить центральную координату в методах делегата regionDid/WillChangeAnimated:, но они вызываются только в начале и в конце жестов. Я также попытался добавить подкласс UIPinchGestureRecognizer, который сбрасывает центральную координату, когда касания перемещаются, но это приводило к устранению сбоев.


Изменить: Для тех, кто заинтересован, для меня работает следующее.

// CenterGestureRecognizer.h
@interface CenterGestureRecognizer : UIPinchGestureRecognizer

- (id)initWithMapView:(MKMapView *)mapView;

@end

// CenterGestureRecognizer.m
@interface CenterGestureRecognizer ()

- (void)handlePinchGesture;

@property (nonatomic, assign) MKMapView *mapView;

@end

@implementation CenterGestureRecognizer

- (id)initWithMapView:(MKMapView *)mapView {
  if (mapView == nil) {
    [NSException raise:NSInvalidArgumentException format:@"mapView cannot be nil."];
  }

  if ((self = [super initWithTarget:self action:@selector(handlePinchGesture)])) {
    self.mapView = mapView;
  }

  return self;
}

- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
  return NO;
}

- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
  return NO;
}

- (void)handlePinchGesture {
  CLLocation *location = self.mapView.userLocation.location;
  if (location != nil) {
    [self.mapView setCenterCoordinate:location.coordinate];
  }
}

@synthesize mapView;

@end

Затем просто добавьте его в свой MKMapView:

[self.mapView addGestureRecognizer:[[[CenterGestureRecognizer alloc] initWithMapView:self.mapView] autorelease]];

Ответ 1

Когда пользователь зажимает экран на самом устройстве (в отличие от симулятора), он вызывает как поворот, так и жест щепотки - пинч содержит элемент "масштабирования" движения, а кастрюля содержит вертикальные и горизонтальное изменение. Вам нужно перехватить и заблокировать панорамирование, а это значит, что используйте UIPanGestureRecognizer.

Установите scrollEnabled в NO, затем добавьте координату UIPanGestureRecognizer в reset. Комбинация блокирует панорамирование с одним пальцем и компонент панорамирования пинча.


Изменить, чтобы добавить дополнительные сведения и после просмотра кода: touchesMoved:withEvent вызывается после того, как панорама уже началась, поэтому, если вы измените центр MKMapView, вы получите хеши- которые вы описали. Вам действительно нужно создать UIPanGestureRecognizer с целевым действием, например:

    UIPanGestureRecognizer *pan = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didRecognizePan)] autorelease];
    pan.delegate = self;
    [self.mapView addGestureRecognizer:pan];

... а затем добавьте метод didRecognizePan к вашему контроллеру и сделайте там сброс центра.

Ответ 2

Догадайтесь, но попробовали ли вы установить scrollEnabled на NO в начале regionWillChangeAnimated:?

Ответ 3

Просто догадка. В начале регионаWillChangeAnimated: сохраните текущую область карты, затем непрерывно обновляйте область через NSTimer, используя self.myMapView.region = theSavedRegion или аналогичный. Затем отключите таймер при вызове regionDidChangeAnimated:

Однако у вас может возникнуть проблема, когда обновление региона с помощью NSTimer вызывает повторение запроса regionWillChangeAnimated.

Попробуйте и посмотрите, что произойдет.