位置管理器始终在工作,但在使用时不工作

location manager working on Always but not When In Use

在 Apple 坚持让用户在位置管理器的 "Always" 和 "When In Use" 之间进行选择之前,我有一个运行良好的应用程序。 该应用程序使用 iBeacons 发送玩游戏的邀请并接受。
When "Always" is selected the beacons work fine but when I switch to "When In Use" they don't work at all. 我开始使用 "Always" 但更改以下代码以让用户选择。 在应用程序的 plist 中,我添加了 "Privacy-Location Always and When In Use Usage Descriptions and Privacy-Location When In Use Usage Description" 并删除了 "Privacy-Location Always Usage Description".

在应用程序的委托中我有这个

- (void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status{

    if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedAlways){
        NSLog(@"Always");
        AlertView2 = [[UIAlertView alloc] initWithTitle:@"Dual player on two devices is enabled."
                                                message:@"To save battery power go to Settings/Privacy/Location Services and choose \"Never\" when not using I'M GAME. Two people can still play on one device when in \"Never\" mode. To recieve invitations to play only when the app is open select \"When In Use\"."
                                               delegate:nil
                                      cancelButtonTitle:@"OK"
                                      otherButtonTitles:nil];
        [AlertView2 show];
        [[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"accessKey"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedWhenInUse){
        NSLog(@"WhenInUse");
        AlertView2 = [[UIAlertView alloc] initWithTitle:@"Dual player on two devices is enabled."
                                                message:@"To save battery power go to Settings/Privacy/Location Services and choose \"Never\" when not using I'M GAME. Two people can still play on one device when in \"Never\" mode. To recieve invitations to play while app is in background select \"Always\"."
                                               delegate:nil
                                      cancelButtonTitle:@"OK"
                                      otherButtonTitles:nil];
        [AlertView2 show];
        [[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"accessKey"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusRestricted){
        NSLog(@"restricted");
    }

    if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
        NSLog(@"denied");
        AlertView2 = [[UIAlertView alloc] initWithTitle:@"Dual player on a single device Only."
                                                message:@"To play on two devices go to Settings Privacy/Location Services and choose \"Always\" or \"When In Use\" for I'M GAME. In \"Always\" you can recieve invites while app is in background, in \"When In Use\" invites only appear when the app is on screen. To preserve battery choose \"Never\" when not using I'M GAME."
                                               delegate:nil
                                      cancelButtonTitle:@"OK"
                                      otherButtonTitles:nil];
        [AlertView2 show];
        [[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"accessKey"];
        [[NSUserDefaults standardUserDefaults] synchronize];

    }
    if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusNotDetermined){
        NSLog(@"undetermined2");
         [locationManager requestAlwaysAuthorization];
       [locationManager requestWhenInUseAuthorization];
    }


}

iBeacon 是否需要将 Privacy-Location 设置为 "Always" 才能工作?

所以我刚刚发现在 "When In Use" 中您无法监控信标区域是否进入或退出,只能找到它的范围。所以我想问题是我将如何使用范围向我的用户发送通知。

当您授权您的应用仅在前台时进行信标测距,只需一个 didRangeBeacons 回调即可轻松模拟 entry/exit 逻辑。

  1. 设置一个class变量:

    var beaconLastSeen: Date? = nil
    
  2. 将此代码添加到您的 didRangeBeacons 方法中:

    if beacons.count > 0 {
      if beaconLastSeen == nil {
         // call didEnterRegion logic here
      }
      beaconLastSeen = Date()
    }
    else {
      if beconLastSeen != nil && Date() - beaconLastSeen > 30 {
         beaconLastSeen = nil
         // call didExitRegion logic here
      }
    }
    

您将在最后一次检测到信标 30 秒后收到退出事件。第一次看到你会得到一个进入事件。

编辑: 这是 Objective C 中的相同代码:

NSDate *beaconLastSeen = nil;

...

if (beacons.count > 0) {
    if (beaconLastSeen == nil) {
        // call didEnterRegion logic here
    }
    beaconLastSeen = [[NSDate alloc] init];
}
else {
    if (beaconLastSeen != nil  && [[[NSDate alloc] init] timeIntervalSinceDate: beaconLastSeen] > 30 ) {
        beaconLastSeen = nil;
        // call didExitRegion logic here
    }
}