重要的更改位置委托方法未被调用

时间:2016-09-17 16:54:51

标签: ios objective-c properties background delegates

我的所有代码都在AppDelegate.m中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];

    _locationMgr = [[CLLocationManager alloc] init];
    [_locationMgr setDelegate:self];
    if([_locationMgr respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
        [_locationMgr setAllowsBackgroundLocationUpdates:YES];
    CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];

    if([launchOptions valueForKey:UIApplicationLaunchOptionsLocationKey] != nil) {
        NSLog(@"relaunching because of significant location change - restarting SLC");
        [_locationMgr startMonitoringSignificantLocationChanges];
    }
    else
    {
        if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
            NSLog(@"launching with authorization to always use location - starting SLC");
            [_locationMgr startMonitoringSignificantLocationChanges];
        }
        else
        {
            NSLog(@"launching with no authorization to always use location - requesting authorization");
            if([_locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)])
                [_locationMgr requestAlwaysAuthorization];
        }
    }

    if([userdefaults objectForKey:@"pfuser"] == nil) {
        NSLog(@"in delegate signup");
        SignUpController *signup = [[SignUpController alloc] init];
        [self.window setRootViewController:signup];
    }
    else {
        ViewController *map = [[ViewController alloc] init];
        [self.window setRootViewController:map];
    }
    [self.window makeKeyAndVisible];

    return YES;
}

- (void)startSignificantChangeUpdates
{
    deviceNotFoundAlertController = [UIAlertController alertControllerWithTitle:@"START" message:@"startSignificantChangeUpdates called" preferredStyle:UIAlertControllerStyleAlert];

    [deviceNotFoundAlertController addAction:deviceNotFoundAlert];
    // Create the location manager if this object does not
    // already have one.
    if (nil == _locationMgr) {
        _locationMgr = [[CLLocationManager alloc] init];
        _locationMgr.delegate = self;
    }

    [CLLocationManager significantLocationChangeMonitoringAvailable];
    [_locationMgr startMonitoringSignificantLocationChanges];
}

-(void)locationManger:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"didFailWithError: %@", error);
    deviceNotFoundAlertController = [UIAlertController alertControllerWithTitle:@"LOCATION FAIL" message:@"didFailWithError" preferredStyle:UIAlertControllerStyleAlert];

    [deviceNotFoundAlertController addAction:deviceNotFoundAlert];
}

// Delegate method from the CLLocationManagerDelegate protocol.
- (void)_locationManager:(CLLocationManager *)manager
      didUpdateLocations:(NSArray *)locations {
    deviceNotFoundAlertController = [UIAlertController alertControllerWithTitle:@"LOCATION UPDATE" message:@"didUpdateLocations called" preferredStyle:UIAlertControllerStyleAlert];

    [deviceNotFoundAlertController addAction:deviceNotFoundAlert];
    // If it's a relatively recent event, turn off updates to save power.
    CLLocation* location = [locations lastObject];
    NSDate* eventDate = location.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (fabs(howRecent) < 15.0) {
        // If the event is recent, do something with it.
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
              location.coordinate.latitude,
              location.coordinate.longitude);
    }
}

没有任何警报发生,似乎没有调用委托方法。

更新

现在我有:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];

    deviceNotFoundAlert = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];

    ...

}

// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
      didUpdateLocations:(NSArray *)locations {
    deviceNotFoundAlertController = [UIAlertController alertControllerWithTitle:@"LOCATION UPDATE" message:@"didUpdateLocations called" preferredStyle:UIAlertControllerStyleAlert];

    [deviceNotFoundAlertController addAction:deviceNotFoundAlert];
    // If it's a relatively recent event, turn off updates to save power.
    CLLocation* location = [locations lastObject];
    NSDate* eventDate = location.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (fabs(howRecent) < 15.0) {
        // If the event is recent, do something with it.
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
              location.coordinate.latitude,
              location.coordinate.longitude);
    }
}

当我测试应用程序时,我在我的房子打开它,然后关闭它,这样当我离开我的房子时,它应该在某个时候发送警报(或3),但我没有得到任何警报委托方法(我发出警报的地方)。

我刚才有一个想法,也许我必须显示来自主UIViewController的警报,而不是AppDelegate

这可能就是我没有看到提醒的原因:How do I add a UIAlertController in app delegate (obj-c)

更新

这就是我现在正在做警报的方式:

deviceNotFoundAlertController = [UIAlertController alertControllerWithTitle:@"START" message:@"startSignificantChangeUpdates called" preferredStyle:UIAlertControllerStyleAlert];

[deviceNotFoundAlertController addAction:deviceNotFoundAlert];

alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
alertWindow.rootViewController = [[UIViewController alloc] init];
alertWindow.windowLevel = UIWindowLevelAlert + 1;
[alertWindow makeKeyAndVisible];
[alertWindow.rootViewController presentViewController:deviceNotFoundAlertController animated:YES completion:nil];

更新

警报似乎不是问题,startSignificantChangeUpdates中的警报从未出现过。一旦我离我的初始位置500米,它应该出现吗?

更新

任何人都可以帮我理解这个吗?

  

从您启动相应位置服务的线程调用委托对象的方法。该线程本身必须有一个活动的运行循环,就像在应用程序的主线程中找到的那样。

更新

我想我弄清楚上面引用的是什么......我现在有了这个 - 我明天会考试。

...

if([launchOptions valueForKey:UIApplicationLaunchOptionsLocationKey] != nil) {
        NSLog(@"relaunching because of significant location change - restarting SLC");
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [_locationMgr startMonitoringSignificantLocationChanges];
        });
    }
    else
    {
        if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
            NSLog(@"launching with authorization to always use location - starting SLC");
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [_locationMgr startMonitoringSignificantLocationChanges];
            });
        }
        else
        {
            NSLog(@"launching with no authorization to always use location - requesting authorization");
            if([_locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)])
                [_locationMgr requestAlwaysAuthorization];
        }
    }

...

我认为代码是在自己的线程上启动位置服务。我注意到的一件事是,当我退出应用程序时,右上角的位置消失了。我刚刚更新到iOS 10.在iOS 9中,右上角的位置箭头将保留在那里,但当应用程序未运行时它只是一个黑色轮廓。这可能只是他们用iOS 10改变的,或者现在因为我更新到10,其他东西现在还没有工作。或者这就是当位置服务在他们自己的线程上运行时会发生的情况。从这里开始:iOS start Background Thread

更新

也许我没有正确使用该帖子,但正如我所说,现在当我关闭应用程序时,位置服务退出。当我在没有线程的情况下执行此操作时,位置服务箭头将保留在右上角,作为轮廓。

更新

我读到服务应该在主线程上启动 - 所以现在我有:

CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];

    NSLog(@"launching with no authorization to always use location - requesting authorization");
    if([_locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [_locationMgr requestAlwaysAuthorization];
    }

    if([launchOptions valueForKey:UIApplicationLaunchOptionsLocationKey] != nil) {
        NSLog(@"relaunching because of significant location change - restarting SLC");
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [_locationMgr startMonitoringSignificantLocationChanges];
        });
    }
    else if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
        NSLog(@"launching with authorization to always use location - starting SLC");
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [_locationMgr startMonitoringSignificantLocationChanges];
        });
    }
    else {
        //
    }

当应用程序关闭时,右侧的箭头不会显示,这对iOS 10来说是新的,他们不再显示它了吗?

更新

我意外删除了:_locationMgr = [[CLLocationManager alloc] init];我投入了,现在箭头一直在那里,今天要去测试。

更新

我测试了它,仍然没有警报。

4 个答案:

答案 0 :(得分:2)

您的委托方法存在问题,请在下面替换

- (void)_locationManager:(CLLocationManager *)manager
      didUpdateLocations:(NSArray *)locations {
}

- (void)locationManager:(CLLocationManager *)manager
      didUpdateLocations:(NSArray *)locations {
}

希望它会对你有所帮助。

答案 1 :(得分:2)

我带着我的电脑在我的车里,看着控制台,我看到现在正在发生重大的位置变化,因为我每隔500米就会获得一次位置更新。警报是唯一不起作用的东西,但它们与程序无关 - 它们只是在那里查看它是否正常工作。它正在使用此代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];

    ...

    _locationMgr = [[CLLocationManager alloc] init];
    [_locationMgr setDelegate:self];

    if([_locationMgr respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
        [_locationMgr setAllowsBackgroundLocationUpdates:YES];

    CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];

    NSLog(@"launching with no authorization to always use location - requesting authorization");
    if([_locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [_locationMgr requestAlwaysAuthorization];
    }

    if([launchOptions valueForKey:UIApplicationLaunchOptionsLocationKey] != nil) {
        NSLog(@"relaunching because of significant location change - restarting SLC");
        [_locationMgr startMonitoringSignificantLocationChanges];
    }
    else if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
        NSLog(@"launching with authorization to always use location - starting SLC");
        [_locationMgr startMonitoringSignificantLocationChanges];
    }
    else {
        //
    }

    ...

    [self.window makeKeyAndVisible];

    return YES;
}

- (void)startSignificantChangeUpdates
{
    // Create the location manager if this object does not
    // already have one.
    if (nil == _locationMgr) {
        _locationMgr = [[CLLocationManager alloc] init];
        _locationMgr.delegate = self;
    }

    [CLLocationManager significantLocationChangeMonitoringAvailable];

    [_locationMgr startMonitoringSignificantLocationChanges];

    deviceNotFoundAlertController = [UIAlertController alertControllerWithTitle:@"START" message:@"startSignificantChangeUpdates called" preferredStyle:UIAlertControllerStyleAlert];

}

-(void)locationManger:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"didFailWithError: %@", error);
}

// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
      didUpdateLocations:(NSArray *)locations {

    // If it's a relatively recent event, turn off updates to save power.
    CLLocation* location = [locations lastObject];
    NSDate* eventDate = location.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (fabs(howRecent) < 15.0) {
        // If the event is recent, do something with it.
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
              location.coordinate.latitude,
              location.coordinate.longitude);
    }
}

答案 2 :(得分:1)

You have written write code, Just add below delegate method in your code.  But startMonitoringSignificantLocationChanges for updating location take 10 to 20 min. and also trigger if location channel change.

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{

}

答案 3 :(得分:1)

[_ locationMgr startMonitoringSignificantLocationChanges];

重要更改位置服务仅在设备位置发生重大变化(例如500米或更长)时才会提供更新。

因此,当您的设备移动超过500米时,您的委托方法每次都会调用一次。

确保您的应用具有后台位置权限。

如果您的应用是在后台或前台,那么它将调用委托方法 否则应用程序将在AppDelegate文件中使用location选项启动,您必须创建位置管理器对象并再次启动位置以获取新位置。

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html