Как инициализировать MKMapView с заданным местоположением пользователя? - PullRequest
19 голосов
/ 17 сентября 2009

Мое приложение знает текущую позицию пользователя (CoreLocation.framework). Как только пользователь открывает новый MapView, его iPhone снова начинает поиск текущей позиции. Можно ли это пропустить или изменить первую позицию пользователя для mkMapView?

Edit:

Можно ли перезаписать MKMapView и использовать другой LocationManager?

Ответы [ 4 ]

42 голосов
/ 30 сентября 2009

Да, можно иметь отдельный объект диспетчера местоположения и назначить его значение для просмотра карты (кстати, я использую '=' ниже в качестве префикса списка, чтобы не допустить обработки кода в SO).

= В вашем UIViewController сохраняются два отдельных свойства: от одного до MKMapView и от одного до CLLocationManager.

= Создайте файл XIB с MKMapView и любым другим окном Chrome, который вы хотите. Подключите розетки к контроллеру. Убедитесь, что MKMapView НЕ соответствует местоположению пользователя.

= Пусть UIViewController реализует протокол CLLocationManagerDelegate, особенно метод locationManager:didUpdateToLocation:fromLocation:, который будет вызываться всякий раз, когда доступно новое значение местоположения. Мы будем устанавливать контроллер в качестве делегата для менеджера местоположения.

= В методе viewController loadView загрузите NIB с MKMapView в нем. Чтобы дать обратную связь с пользователем, вы можете установить счетчик UIActivityIndicatorView и установить его на startAnimating. Тогда вы начинаете с:

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
self.locationManager.distanceFilter = 10; // or whatever
[self.locationManager startUpdatingLocation];

= В locationManager:didUpdateToLocation:fromLocation: проверить, было ли событие обновлено с последних N секунд. Затем скажите менеджеру местоположения прекратить обновление, вращателю - остановить анимацию, получите данные широты и долготы и назначьте их виду карты вместе с диапазоном и областью просмотра, чтобы масштабировать и центрировать в нужном месте.

= Теперь вот сложная часть: «пульсирующий» из синего мрамора является функцией отслеживания местоположения пользователя при просмотре карты. Вам придется на мгновение «подделать», пока не появится реальный (или просто использовать отдельный маркер для текущего местоположения и сохранять его положение самостоятельно). Лично я бы выбрал синий мрамор, с которым пользователь знаком.

= Чтобы сделать так, чтобы он отображался прямо при запуске, вам нужно будет создать пользовательский MKAnnotationView с только синей мраморной графикой, добавленной в местоположение, возвращаемое менеджером местоположений. Это означает, что нужно сделать снимок Mapview с отображением местоположения, затем сделать фотоснимок только с синим мрамором и использовать его в качестве изображения для пользовательского представления аннотации.

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

= Чтобы позволить собственному местонахождению mapview выполнить обновление, добавьте viewDidLoad:

[self.map.userLocation addObserver:self 
forKeyPath:@"location" 
options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) 
context:NULL];
self.map.showsUserLocation = YES; // starts updating user location

= Реализация observeValueForKeyPath. Он вызывается, когда атрибут location карты userlocation имеет значение:

-(void)observeValueForKeyPath:(NSString *)keyPath 
      ofObject:(id)object 
        change:(NSDictionary *)change 
       context:(void *)context 
{
     if ([self.map isUserLocationVisible]) {
         [self.locationManager stopUpdatingLocation];
         self.ownBlueMarble.hidden = YES;
     }
     // The current location is in self.map.userLocation.coordinate
}

= Чтобы избежать задержки прогрева при отображении текущего местоположения, сохраняйте ссылку на viewController, содержащий карту и диспетчер местоположений, чтобы он не исчезал (это немного запирает память, но если вы отпустите его, вы Придется снова подождать, пока MapView загрузит плитки и будет готов к работе).

= В viewWillLoad вы можете вставить последнее известное местоположение в пользовательскую аннотацию bluemarble и показать ее. Включите / выключите отслеживание userLocation, и когда вы получите уведомление, будет работать тот же трюк «скрыть аннотацию, показать реальный мрамор». Запускается собственный менеджер местоположений карты, и когда у него есть данные, вы можете заставить маркер аннотации исчезать.

= Возможно, вы захотите внедрить метод viewController viewWillDisappear и вручную отключить отслеживание userLocation в просмотре карты, чтобы он был отключен по умолчанию при следующем запуске представления. Вы также захотите получить последний известный userLocation и сохранить его для следующего запуска. Таким образом, вы можете выполнять все манипуляции с позиционированием маркеров в методе viewWillAppear и не беспокоиться о вмешательстве userLocation до тех пор, пока вы не будете готовы к этому.

Удачи.

27 голосов
/ 24 сентября 2009

В вашем контроллере:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    CLLocationCoordinate2D coord = {latitude: 37.423617, longitude: -122.220154};
    MKCoordinateSpan span = {latitudeDelta: 1, longitudeDelta: 1};
    MKCoordinateRegion region = {coord, span};
    [mapView setRegion:region];
}

Когда карта появится, она будет находиться в центре рядом с Пало-Альто

0 голосов
/ 28 сентября 2009

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

Допустим, у вас было сокетное соединение с автомобилем дистанционного управления, и этот автомобиль отправлял обратно данные сокета, содержащие информацию о географическом местоположении в полезной нагрузке. Вы можете разобрать это и обновить местоположение миниатюры на вашей карте в режиме реального времени. Свойство userLocation для этого не нужно, но вы можете показать его, если хотите.

Местоположение пользователя доступно только для чтения, можете вы его использовать или нет. Это не означает, что вам нужен другой менеджер местоположения, чтобы сделать все, что вам может понадобиться. Похоже, что ваше приложение на самом деле не нуждается в этой функции, но я могу неправильно понять ваш вопрос.

0 голосов
/ 25 сентября 2009

Попробуйте установить для свойства showUserLocation значение false при инициализации, а затем восстановите region, который ранее имел вид карты (вам, очевидно, придется сохранить его до уничтожения предыдущей карты).

Это то, что вы хотели?

...