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

标签 ios objective-c bluetooth application-state

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

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

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

更新#1

问题...

如何区分 之间的应用程序应用 相比,导致系统级非事件焦点状态(如运行代码以连接到蓝牙)用户 导致系统级非事件焦点,如双击主页按钮?一切都在努力区分导致 applicationWillResignActive 的原因开火的方法。

更新#2

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

如果用户尚未连接到 BT 设备并且它是第一次连接并且出现配对警报,它会触发 applicationWillResignActive方法与双击主页按钮相同。在此方法中,代码会检查 NSUserDefaults flag 看它是否打开(此时是因为 BT 已经到达 CBCentralManagerdidConnectPeripheral 方法并打开它),如果它打开,它会关闭 BT 并切换到扫描 iBeacon .因为该应用程序仍处于打开状态,这显然会导致问题。该应用程序正在运行,因此用户看到 BT 连接,新 View 滑入,配对警报出现,然后新 View 滑出,iBeacon 开始发送通知,供用户在任务切换器中使用。

我已经在 applicationWillEnterBackground 中实现了这个确切的功能。方法,所以这不是答案。我需要有一种方式说“应用程序正在运行,我们收到了警报而不是双击主页,所以请不要关闭 BT 并打开 iBeacon”

最佳答案

两种可能的解决方案:

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

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



您的应用必须执行某些操作才能显示此警报。您可以设置 Date AppDelegate 中的当前时间字段当这种情况发生时,然后当您接到 applicationWillResignActive 的电话时您可以将该时间戳与当前时间进行比较,如果它小于 1 秒左右,那么您就有了一个很好的线索,即蓝牙对话框启动了。

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

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

在调用 applicationWillResignActive 后,您可以请求最多 180 秒的后台运行时间。 ,所以你可以推迟你的清理任务,直到你的应用程序退出到后台后 175 秒。如果用户在 3 分钟内没有回来,则可能是时候进行此清理了。我的博文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

  });
}

关于ios - objective-c 区分 applicationWillResignActive 中的警报消息和任务切换器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45191442/

相关文章:

objective-c - Cocoa:如果用户没有执行任何操作,则隐藏 NSWindow

ios - iOS中的NSNumber等效错误

ios - Swizzling SKStoreProductViewController viewWillAppear 或 viewDidAppear 不工作

android - 列出连接的蓝牙设备?

C# 控制台应用程序通过蓝牙与 Arduino 对话

iphone - 如何根据当前时间加载不同的 View Controller (使用 -(void)didTap...)?

ios - 在 64 位处理器上运行时出现 Core Audio 错误

java - 在蓝牙中仅检测到一个设备

iphone - 使用适用于 iOS 的 Dropbox Chooser SDK 时无法生成链接错误

ios - Swift:未设置请求授权 header