В моем UIViewController initWithNibNameOrNil
я вызываю:
locationManager = [CLLocationManager new];
чтобы создать объект, затем позже в viewDidAppear
я вызываю:
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
Но я никогда не получаю обновления местоположения; менеджер местоположения никогда не начинает обновлять местоположение. Но если я заменю ту же строку initWithNibNameOrNil
на:
locationManager = [[myAppDelegate appDelegate] locationManager];
все отлично работает, кроме случайных вылетов иногда при
locationManager.delegate = self;
задается в самой следующей строке после того, как менеджер местоположения установлен на уже выделенный менеджер в делегате приложения. Ничто из этого не имеет для меня смысла; Я не понимаю, почему одно отличается от другого, а тем более почему ни один из них не работает последовательно. Может кто-нибудь просветить меня?
Обзор:
Способ 1 (не работает):
В MapView.m:
initWithNibNameOrNil
:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
locationManager = [CLLocationManager new];
locationManager.delegate = self;
locationManager.distanceFilter = kCLHeadingFilterNone;
locationManager.headingFilter = 3;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull))
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
else
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//more setup irrelevant to the question
}
return self;
}
viewDidAppear
:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
Примечания. При использовании этого метода создания менеджера местоположения службы определения местоположения никогда не включаются после вызова startUpdatingLocation в viewDidAppear, поэтому никакие обновления местоположения никогда не получаются.
Способ 2 (в основном работает):
В myAppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
self.locationManager = [CLLocationManager new];
self.locationManager.distanceFilter = kCLHeadingFilterNone;
self.locationManager.headingFilter = 3;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull))
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
else
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//more irrelevant setup
}
В MapView.m:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
locationManager = [[Trail_TrackerAppDelegate appDelegate] locationManager];
locationManager.delegate = self;
//more irrelevant setup
}
return self;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
Примечания: этот метод распределения работает, за исключением того, что если я нажимаю MapView, затем выталкиваю его, снова нажимаю, снова выталкиваю, затем снова пытаюсь нажать, я получаю сбой каждый раз на строке в initWithNib ... где я установил делегата на себя; NSZombieEnabled
говорит:
-[CLLocationManager setDelegate:]: message sent to deallocated instance 0x9540ad0
Интересно...
NSLog(@"%s: %@; %@", PRETTY_FUNCTION, self, locationManager) говорит следующее:
-[MapView initWithNibName:bundle:]: <MapView: 0x92ae3e0>; <CLLocationManager: 0x92a3560>
Способ 3 (работает везде):
В MapView.m:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
locationManager = [CLLocationManager new];
locationManager.delegate = self;
locationManager.distanceFilter = kCLHeadingFilterNone;
locationManager.headingFilter = 3;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull))
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
else
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
Примечания: все выделение и настройка выполняются в viewDidAppear
, и я не получаю никаких сбоев после повторного нажатия/выталкивания контроллера представления. Это здорово, но мне не нравится выделение в viewDidAppear
, потому что приложение отстает всего на мгновение, потому что (я думаю) выделение locationManager забивает основной поток на это время. Я просто действительно не понимаю, почему метод 1 вообще не работает, метод 2 вылетает, а метод 3 работает. Разве все они не делают более или менее одно и то же?
Извините за весь код и поздравляю всех, кто прошел весь этот лабиринт вопросов! :)
NSLog("%s: %@; %@", __PRETTY_FUNCTION__, self, locationManager)
, а затем скопируйте/вставьте результаты в свой вопрос. - person Firoze Lafeer   schedule 11.12.2011