objective-c 在 applicationWillResignActive 中区分警报消息和任务切换器

objective-c differentiate between alert message and task switcher in applicationWillResignActive

我正在尝试在 applicationWillResignActive 期间 运行 一些代码,当用户打开任务切换器时它工作正常,直到我开始在我的应用程序中使用蓝牙。

当蓝牙尝试连接到设备时,它会显示一个警告 window 询问用户是否要与设备配对。此警报足以触发 applicationWillResignActive 方法,然后 运行 是我的代码,用于当应用程序被导航离开(任务切换器)时。这会导致一个大问题,因为我打算在切换时 运行 的代码会关闭实际应用程序中一些非常需要的功能。因此,一旦他们在该警报上按 "pair" 或 "cancel",我的所有应用程序都会停止正常运行,因为该应用程序失去了焦点。

在此期间,我尝试使用此检测应用程序的状态... NSUInteger state = [[UIApplication sharedApplication] applicationState]; 当然,当警报弹出时它会被认为是活动的,而在任务切换器中时它会被认为是非活动的。但是,对于这两个用例,它都显示为活跃的情况并非如此。

更新 #1

问题...

我如何在应用程序中区分 app 导致系统级非活动焦点状态(如 运行ning 代码连接到蓝牙)与 user 导致系统级非活动焦点,如双击主页按钮?所有这些都在努力区分导致 applicationWillResignActive 方法触发的原因。

更新 #2

此功能的目的是在蓝牙连接到设备时在 NSUserDefaults 中设置一个标志。此标志正在 "observed" 并用于触发将视图控制器更改为与此新 BT 连接相关的页面。当用户双击主页按钮并移动到任务切换器时,我关闭 BT 并切换到 iBeacon,以便我可以通知事件。当前实现的所有 bar 1 用例都很好。

如果用户尚未连接到 BT 设备并且它是第一次连接并且出现配对警报,它会触发 applicationWillResignActive 方法,就像双击主页按钮一样。在这种方法中,代码然后检查 NSUserDefaults 标志以查看它是否打开(此时是因为 BT 已经到达 CBCentralManagerdidConnectPeripheral 方法并打开它打开),如果它打开,它会关闭 BT 并切换到扫描 iBeacon。因为该应用程序仍处于打开状态,所以这显然会导致问题。该应用程序正在 运行ning,因此用户可以看到 BT 连接、新视图滑入、配对提醒出现,然后新视图立即滑出并且 iBeacon 开始发送通知,用于在用户处于任务切换器。

我已经在 applicationWillEnterBackground 方法中实现了这个确切的功能,所以这不是答案。我需要有一种说法 "the app is running right now and we've received an alert instead of double tapping home, so please don't turn off BT and turn on iBeacon yet"

两种可能的解决方案:

1.答案可能就在这句话中:

When bluetooth tries to connect to a device it shows an alert window asking if the user wants to pair the device.

您的应用程序必须执行某些操作 才能显示此警告。当发生这种情况时,您可以在 AppDelegate 中将 Date 字段设置为当前时间,然后当您接到 applicationWillResignActive 的电话时,您可以将该时间戳与当前时间进行比较,如果不到 1 秒左右,您就很清楚蓝牙对话启动了。

当然,这并非万无一失。正如@danh 在他的评论中指出的那样, iOS 的设计使这变得非常困难。您无法确定蓝牙对话框是否打开,或者用户或 OS 是否恰好同时将其他东西带到了前台。更重要的是,即使出现蓝牙对话框,用户也可能在那一刻决定去检查他或她的电子邮件或开始浏览 Facebook。在这种情况下,蓝牙对话框确实将您的应用程序发送到后台, 用户离开了该应用程序。不幸的是,iOS 并没有真正为您提供区分两者的方法。

2。您可以使用后台任务来处理清理逻辑。

您可以在调用 applicationWillResignActive 后请求最多 180 秒的后台 运行 时间,这样您就可以推迟清理任务,直到您的应用程序退出 175 秒后背景。如果用户在 3 分钟内没有回来,可能是时候进行清理了。我的博客 post here 展示了设置后台任务的基础知识。它专门用于延长信标测距时间,但您可以将任何您想要的逻辑放入后台代码块中,如下所示:

- (void)extendBackgroundRunningTime {
  if (_backgroundTask != UIBackgroundTaskInvalid) {
    // if we are in here, that means the background task is already running.
    // don't restart it.
    return;
  }
  NSLog(@"Attempting to extend background running time");

  __block Boolean self_terminate = YES;

  _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"DummyTask" expirationHandler:^{
    NSLog(@"Background task expired by iOS");
    if (self_terminate) {
        [[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
        _backgroundTask = UIBackgroundTaskInvalid;
    }
  }];



 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"Background task started.  Waiting 175 seconds before cleanup.");
    [NSThread sleepForTimeInterval:175];

    //TODO: perform cleanup code if app is not in the foreground by now

  });
}