Как получить текущую координату CLLocationManager

У меня есть UIViewController, где я хочу отобразить карту с центром в текущей позиции.

Метод AppDelegate didFinishLaunchingWithOptions выглядит так:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.locationManager = [[CLLocationManager alloc] init];

    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
        [self.locationManager requestAlwaysAuthorization];
    }
    [self.locationManager startUpdatingLocation];

    return YES;
}

Мой класс UIViewController.m выглядит так:

@interface GMapViewController ()<CLLocationManagerDelegate>

@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (strong, nonatomic) CLLocation *currentLocation;

@end

@implementation GMapViewController

#pragma mark - Lifecycle methods

- (void)viewDidLoad {
    [super viewDidLoad];

    self.currentLocation = [CLLocation new];

    [[[AppDelegate appDelegate] locationManager] setDelegate:self];

    MKCoordinateRegion visibleRegion;
    visibleRegion.center = self.currentLocation.coordinate;
    visibleRegion.span = MKCoordinateSpanMake(200, 200);

    [self.mapView setRegion:visibleRegion animated:YES];
}

#pragma mark - CLLocationManagerDelegate's methods

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    self.currentLocation = [locations lastObject];
}

Дело в том, что метод делегата didUpdateLocations CLLocationManager вызывается слишком поздно, поскольку свойство Текущее местоположение не имеет значения при вызове viewDidLoad.

Как я могу получить текущую координату перед вызовом viewDidLoad?

Почему бы вам просто не импортировать CoreLocation в свой контроллер представления?

El Tomato 10.06.2018 15:05

CoreLocation был импортирован в AppDelegate

ovidiu.developer 10.06.2018 15:20

Скорее всего, viewDidLoad в GMapViewController вызывается раньше, чем didFinishLaunchingWithOptions в AppDelegate. Лениво инициализируйте locationManager и переместите startUpdatingLocation в viewDidLoad после установки делегата.

vadian 10.06.2018 15:21

@vadian, didFinishLaunchingWithOptions вызывается раньше, чем viewDidLoad

ovidiu.developer 10.06.2018 15:25

Тем не менее, после установки делегата вызовите startUpdatingLocation.

vadian 10.06.2018 15:28

@vadian, я переместил вызов startUpdatingLocation после установки делегата, лучших результатов нет

ovidiu.developer 10.06.2018 15:36
"Как мне получить текущую координату перед вызовом viewDidLoad" - нельзя и не надо пробовать. Обновите регион карты при вызове didUpdateLocations. Покажи что-нибудь разумное, пока этого не произошло.
rmaddy 10.06.2018 17:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
67
1

Ответы 1

Вам необходимо обновить вид карты после обновления местоположения; это займет некоторое время.

У вас также есть потенциальное состояние гонки, потому что вы вызываете startUpdatingLocation в своем AppDelegate, но контроллер представления не устанавливается в качестве делегата до viewDidLoad. Делегат почти наверняка будет установлен до обновления местоположения, но вы не можете этого гарантировать.

Я бы посоветовал вам переместить все в свой контроллер представления, и если вы хотите обновить карту только один раз, используйте requestLocation:

@interface GMapViewController ()<CLLocationManagerDelegate>

@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (strong, nonatomic) CLLocation *currentLocation;
@property (strong, nonatomic) CLLocationManager *locationManager;

@end

@implementation GMapViewController

#pragma mark - Lifecycle methods

- (void)viewDidLoad {
    [super viewDidLoad];

    self.locationManager = [[CLLocationManager alloc] init];
    self.currentLocation = nil;

        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
            [self.locationManager requestAlwaysAuthorization];
        } else {
            [self.locationManager requestLocation];
}

-(void) setMapTo:(CLLocation *)location {
      MKCoordinateRegion visibleRegion;
      visibleRegion.center =location.coordinate;
      visibleRegion.span = MKCoordinateSpanMake(200, 200);

     [self.mapView setRegion:visibleRegion animated:YES];
}

#pragma mark - CLLocationManagerDelegate's methods

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    CLLocation *currentLocation = [locations lastObject];
    dispatch_async(dispatch_get_main_queue(), ^{
          [self setMapTo:currentLocation];
    });
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    if (status != kCLAuthorizationStatusRestricted && status != kCLAuthorizationStatusDenied) {
        [manager requestLocation];
    }
}

Если вы просто хотите, чтобы карта постоянно отслеживала местоположение пользователя, вы можете просто установить для свойства userTrackingMode вида карты значение MKUserTrackingModeFollow.

Другие вопросы по теме