iPhone: уменьшение и уменьшение масштаба MKMapView приводит к смещению карты region.center

У меня есть простое приложение для iphone, в котором используется MKMapView. Он имеет сегментированный элемент управления, который позволяет изменять масштаб области (улица, район, город, штат, мир). Он работает нормально, но если я уменьшу масштаб до уровня штата и вернусь к улице, я замечаю, что центральная точка сместилась.

Ниже приведены два метода делегата, которые вызываются до и после изменения региона, и мой метод changeZoom, который вызывается сегментированным элементом управления:

- (void)mapView:(MKMapView *)mView regionDidChangeAnimated:(BOOL)animated
{
 MKCoordinateRegion region = [mapView region];

 NSLog(@"Region DID change.   Center is now %f,%f,  Deltas=%f,%f", 
    region.center.latitude, region.center.longitude,
    region.span.latitudeDelta, region.span.longitudeDelta);
}

- (void)mapView:(MKMapView *)mView regionWillChangeAnimated:(BOOL)animated
{
 MKCoordinateRegion region = [mapView region];

 NSLog(@"Region WILL change.   Center is now %f,%f,  Deltas=%f,%f", 
    region.center.latitude, region.center.longitude,
    region.span.latitudeDelta, region.span.longitudeDelta);
}


- (IBAction)changeZoom:(id)sender
{
 UISegmentedControl *sc = (UISegmentedControl *)sender;

 float mile_range = 1;

 NSLog(@"changeZoom called.   MapView currently is Center=%f,%f  Deltas=%f,%f", 
    mapView.region.center.latitude, mapView.region.center.longitude,
    mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta );

 switch ( [sc selectedSegmentIndex] )
 {
  case 0: /* Street */
   mile_range=1;
   break;
  case 1: /* Hood */
   mile_range=2;
   break;
  case 2: /* City */
   mile_range=30;
   break;
  case 3: /* State */
   mile_range=500;
   break;
  case 4: /* World */
   mile_range=4000;
   break;
  default: /* Error */
   NSLog(@"Unknown segment selected from the UISegmentedControl!!!!!!!!!!!!!!");
   return;
   break;
 }

 originalZoomCenter = mapView.region.center;
 MKCoordinateRegion region;
    region = MKCoordinateRegionMakeWithDistance( originalZoomCenter, mile_range/MILES_PER_METER, mile_range/MILES_PER_METER );
    region = [mapView regionThatFits: region];

 NSLog(@"Calling setRegion Center=%f,%f  Deltas=%f,%f", 
    region.center.latitude, region.center.longitude,
    region.span.latitudeDelta, region.span.longitudeDelta );

    [mapView setRegion: region animated: YES];

 NSLog(@"After setRegion Center=%f,%f  Deltas=%f,%f", 
    mapView.region.center.latitude, mapView.region.center.longitude,
    mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta );
}

Если я запускаю приложение, и оно начинается с уровня масштабирования улицы в моем текущем местоположении, а затем я щелкаю, чтобы уменьшить масштаб до уровня штата и вернуться к уровню улицы, я получаю следующий вывод в консоли:

Region WILL change.   Center is now 30.145127,-40.078125,  Deltas=151.851332,225.000000
Region DID change.   Center is now 37.331676,-122.030725,  Deltas=0.024842,0.027466
changeZoom called.   MapView currently is Center=37.331676,-122.030725  Deltas=0.024842,0.027466
Calling setRegion Center=37.331676,-122.030725  Deltas=12.708100,14.062500
Region WILL change.   Center is now 37.331676,-122.030725,  Deltas=0.024842,0.027466
After setRegion Center=37.331676,-122.030725  Deltas=0.024842,0.027466
Region DID change.   Center is now 37.335224,-122.036133,  Deltas=12.707505,14.062500 
changeZoom called.   MapView currently is Center=37.335224,-122.036133  Deltas=12.707505,14.062500
Calling setRegion Center=37.335224,-122.036133  Deltas=0.024841,0.027466
Region WILL change.   Center is now 37.335224,-122.036133,  Deltas=12.707505,14.062500
After setRegion Center=37.335224,-122.036133  Deltas=12.707505,14.062500
Region DID change.   Center is now 37.335224,-122.036133,  Deltas=0.024841,0.027466

Таким образом, все вызовы, которые я делаю в моем коде, выполняются, как ожидалось, и центр не меняется, но когда я наблюдаю за методом regionDidChangeAnimated методом MKMapViewDelegate, я вижу, что центр перемещается. Если я установлю там точку останова, я увижу стек, который выглядит так:

#0 0x00034c4c in -[MapViewController mapView:regionDidChangeAnimated:] at MapViewController.m:209
#1 0x01fbf7bf in -[MKMapView _didChangeRegionMidstream:]
#2 0x003e11f5 in -[UIView(Gestures) animator:stopAnimation:]
#3 0x003743be in -[UIAnimator stopAnimation:]
#4 0x00374154 in -[UIAnimator(Static) _advance:]
#5 0x0264d719 in HeartbeatTimerCallback
#6 0x01d28ac0 in CFRunLoopRunSpecific
#7 0x01d27c48 in CFRunLoopRunInMode
#8 0x0264a78d in GSEventRunModal
#9 0x0264a852 in GSEventRun
#10 0x00307003 in UIApplicationMain
#11 0x00002194 in main at main.m:14

На самом деле это не помогает мне понять, почему центр будет перемещаться. Я запускал это как в симуляторе, так и на устройстве, и это меня немного сводит с ума.

Если у кого-то есть понимание того, что вызывает смещение центра, я был бы признателен за любые указатели.


person Pat    schedule 22.01.2010    source источник
comment
Ошибки, которые я вижу при масштабировании от дельты 1 мили до: Ошибка города (30 миль) составляет 0,12 мили (0,4%) Ошибка штата (500 миль) составляет 0,78 мили (0,156%) Ошибка мира (1000 миль) составляет 3,17 миль (0,317%) Таким образом, центр смещается на долю процента, когда я уменьшаю масштаб до этих длинных / широтных дельт и обратно. Интересно, следует ли этого ожидать, поскольку усечение с плавающей запятой может происходить внутри MKMapView класс ??   -  person Pat    schedule 27.01.2010


Ответы (1)


По моему опыту, свойство region карты повторно вычисляется после того, как его регион изменен программно с помощью общедоступных API-интерфейсов или с помощью события пользовательского интерфейса.

При уменьшении масштаба вы теряете точность в центре карты (один пиксель покрывает большую область). Затем, после установки региона с setRegion:[animated:], (вычисленное таким образом) map.region может отличаться от региона, который был задан в setRegion. Это могло бы объяснить получаемые вами дельты.

Чтобы решить вашу конкретную проблему, я бы предпочел сохранять центр карты каждый раз, когда пользователь перемещает карту, и использовать сохраненное значение для масштабирования вместо того, чтобы доверять map.region.center.

person Frizlab    schedule 17.01.2012