1

我的 Apple Watch 应用程序需要一些数据,并从相应的 iPhone 应用程序请求这些数据。为了满足请求,iPhone 应用程序需要用户位置。在收到并使用真正的 Apple Watch 进行测试后,我发现我的 iPhone 应用程序在后台运行时没有接收到位置更新。如果 iPhone 应用程序在前台处于活动状态,则它可以正常工作。使用模拟器,它在这两种情况下都有效。

在这两种情况下(活动和后台),WatchKit 扩展程序调用并成功启动 iPhone 应用程序并一直运行,直到在 iPhone 应用程序中调用 startUpdatingLocation。但是如果应用程序在后台运行,didUpdateLocations 永远不会被调用。

我尝试了 requestAlwaysAuthorization 和 requestWhenInUseAuthorization。没有不同。然后我还激活了功能内的“位置更新”后台模式。但又没有区别。

是否有其他人面临同样的问题并找到了一种在后台也接收位置的方法?

这里有一些代码。首先检查是否需要授权。

// iOS 8 check to avoid crash on older iOS
    if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
    {
        [self requestLocationAlwaysAuthorization];
    }
    else
    {
        [self runLocationUpdate];
    }

在这里检查正确的位置管理员权限。

- (void)requestLocationAlwaysAuthorization
{
CLAuthorizationStatus currentAuthStatus = [CLLocationManager authorizationStatus];

if (currentAuthStatus == kCLAuthorizationStatusDenied)
{
    //request user to change setting
}
else if (currentAuthStatus == kCLAuthorizationStatusRestricted)
{
    //request user to change setting
}
else if (currentAuthStatus == kCLAuthorizationStatusNotDetermined)
{
    [self.locationManager requestAlwaysAuthorization];

    [self runLocationUpdate];
}
else if (currentAuthStatus == kCLAuthorizationStatusAuthorizedWhenInUse)
{
    //maybe when in use is also enough?
    [self runLocationUpdate];
}
else if (currentAuthStatus == kCLAuthorizationStatusAuthorizedAlways)
{
    //all ok
    [self runLocationUpdate];
}

}

这里调用 startUpdatingLocation。只有在 iPhone 应用程序处于活动状态时才会调用 didUpdateLocations 委托。

-(void)runLocationUpdate
{
    [self.locationManager startUpdatingLocation];
}
4

1 回答 1

3

需要检查和注意的三件事:

  1. 像这样的位置权限[self.locationManager requestAlwaysAuthorization];仅由操作系统确认一次。如果您已经请求权限,无论级别如何,操作系统都不会向用户显示请求。操作系统只会传递请求并保持权限级别不变。只有在 [CLLocationManager authorizationStatus]返回kCLAuthorizationStatusNotDetermined. 在所有其他情况下,您必须通过显示警报或其他形式的 UI 显示来手动请求权限。另请注意,操作系统会保留它是否已显示请求,即使您删除应用程序并重新安装它也是如此。因此,要进行测试,您需要重置模拟器的内容或 iPhone 的位置隐私。

  2. NSLocationAlwaysUsageDescription确保您已为AND添加了 plist 键NSLocationWhenInUseUsageDescription如果您没有将其添加到您的 plist 中,操作系统将忽略任何位置权限请求。

  3. 如果您想requestAlwaysAuthorization在手机应用程序处于后台时从手机(不是手表应用程序扩展程序)获取位置数据,还需要您在项目>目标>功能下注册后台模式位置更新。

更新 使用后台任务让您的应用程序有时间在后台响应。像这样的东西:

-(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply{

    UIApplication *app = [UIApplication sharedApplication];

    UIBackgroundTaskIdentifier bgTask __block = [app beginBackgroundTaskWithName:@"watchAppRequest" expirationHandler:^{

        [[UIApplication sharedApplication] endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;

    }];

//make your calls here to your tasks, when finished, send the reply then terminate the background task

//send reply back to watch
reply(replyInfo);

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [app endBackgroundTask:bgTask];
        bgTask=UIBackgroundTaskInvalid;
    });
}
于 2015-05-15T15:33:36.867 回答