У меня есть 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 был импортирован в AppDelegate
Скорее всего, viewDidLoad в GMapViewController вызывается раньше, чем didFinishLaunchingWithOptions в AppDelegate. Лениво инициализируйте locationManager и переместите startUpdatingLocation в viewDidLoad после установки делегата.
@vadian, didFinishLaunchingWithOptions вызывается раньше, чем viewDidLoad
Тем не менее, после установки делегата вызовите startUpdatingLocation.
@vadian, я переместил вызов startUpdatingLocation после установки делегата, лучших результатов нет
didUpdateLocations. Покажи что-нибудь разумное, пока этого не произошло.





Вам необходимо обновить вид карты после обновления местоположения; это займет некоторое время.
У вас также есть потенциальное состояние гонки, потому что вы вызываете 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.
Почему бы вам просто не импортировать CoreLocation в свой контроллер представления?