我试图在applicationWillResignActive
期间运行一些代码,当用户打开任务切换器时它已经正常工作,直到我开始在我的应用程序中使用蓝牙。
当蓝牙尝试连接到设备时,它会显示一个警告窗口,询问用户是否要配对设备。此警报足以触发applicationWillResignActive
方法,然后在应用程序远离(任务切换器)时运行我的代码。这导致了一个大问题,因为我打算在切换时运行的代码运行,关闭实际应用程序中一些非常需要的功能。所以一旦按下"配对"或者"取消"在那个警报上,我的所有应用都停止运作,因为应用已失去焦点。
我试图在此期间检测应用程序的状态... NSUInteger state = [[UIApplication sharedApplication] applicationState];
当然认为当警报弹出时会被视为活动状态,而在任务切换器中则是非活动状态。但是,对于这两种用例而言,情况并非如此。
问题......
如何区分 app 之间的应用程序导致系统级非活动焦点状态(如运行代码连接到蓝牙),而用户导致系统级别处于非活动状态重点像双击主页按钮?所有这些都是为了区分导致applicationWillResignActive
方法触发的原因。
此功能的目的是在蓝牙连接到设备时在NSUserDefaults
中设置标志。正在观察这个标志"并用于触发将视图控制器更改为与此新BT连接相关的页面。当用户双击主页按钮并移动到任务切换器时,我关闭BT并切换到iBeacon,以便我可以通知事件。所有条形码1的用例都适用于当前实现。
如果用户尚未连接到BT设备并且它第一次连接并且配对警报出现,则会触发applicationWillResignActive
方法,就像双击主页按钮一样。在此方法中,代码然后检查该NSUserDefaults
标志以查看它是否已打开(此时这是因为BT已经到达CBCentralManager
' s didConnectPeripheral
方法并将其打开)如果它打开,它会关闭BT并切换到扫描iBeacon。因为应用程序仍然打开,这显然会导致问题。该应用程序正在运行,因此用户看到BT连接,新视图滑入,配对警报出现,然后新视图向右滑动,iBeacon开始发送用户在任务中的通知切换器。
我已经在applicationWillEnterBackground
方法中发生了这个确切的功能,因此不是答案。我需要有一种说法"该应用程序现在正在运行,我们已经收到警报而不是双击回家,所以请不要关闭BT并打开iBeacon&#34 ;
答案 0 :(得分:1)
两种可能的解决方案:
<强> 1。答案可能在于以下陈述:
当蓝牙尝试连接到设备时,它会显示一个警告窗口,询问用户是否要配对设备。
您的应用必须执行某些内容才能显示此警报。当发生这种情况时,您可以将Date
字段设置为AppDelegate
中的当前时间,然后当您拨打applicationWillResignActive
时,可以将该时间戳与当前时间进行比较,如果它是&lt; 1秒左右,你有一个非常好的线索,蓝牙对话框上升了。
当然,这不是万无一失的。正如@danh在评论中指出的那样,iOS的设计使得这非常困难。您无法确定蓝牙对话框是否已启动,或者用户或操作系统是否恰好同时将其他内容带到了前台。更重要的是,即使蓝牙对话框出现,用户也可能决定在那个时刻检查他或她的电子邮件或开始浏览Facebook。在这种情况下,蓝牙对话框确实将您的应用程序发送到后台, AND 用户导航离开应用程序。不幸的是,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
});
}