CoreBluetooth 状态保存问题:在 iOS 7.1 中未调用 willRestoreState
大家好。过去几周我一直在从事蓝牙 LE 项目,但遇到了障碍。我无法在 iOS 7/7.1 中正常恢复状态。我已经遵循(我认为)Apple 制定的所有步骤,并在其他堆栈溢出帖子中获得了一些线索。
- 我向 plist 添加了适当的蓝牙权限
- 当我创建我的中央管理器时,我给它一个恢复标识符键。
- 我总是用相同的 key 实例化 CM
- 我将 willRestoreState 函数添加到 CM 委托(delegate)
我的测试用例:
- 连接到外围设备
- 确认连接
- 模拟内存回收 (kill(getpid(), SIGKILL);)
- 传输数据
iOS 7 结果:
应用程序将在 AppDelegate didFinishLaunchingWithOptions 函数中响应,但 launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey] 中的 NSArray 的内容始终是一个空数组。
iOS 7.1 上的结果:
进步了!我可以 100% 的时间在 UIApplicationLaunchOptionsBluetoothCentralsKey 数组中看到我的 CentralManager key ,但从未调用 willRestoreState。
代码:
//All of this is in AppDelegate for testing
@import CoreBluetooth;
@interface AppDelegate () <CBCentralManagerDelegate, CBPeripheralDelegate>
@property (readwrite, nonatomic, strong) CBCentralManager *centralManager;
@end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionRestoreIdentifierKey:@“myCentralManager”}];
//Used to debug CM restore only
NSArray *centralManagerIdentifiers = launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];
NSString *str = [NSString stringWithFormat: @"%@ %lu", @"Manager Restores: ", (unsigned long)centralManagerIdentifiers.count];
[self sendNotification:str];
for(int i = 0;i<centralManagerIdentifiers.count;i++)
{
[self sendNotification:(NSString *)[centralManagerIdentifiers objectAtIndex:i]];
}
return YES;
}
- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)state {
activePeripheral = [state[CBCentralManagerRestoredStatePeripheralsKey] firstItem];
activePeripheral.delegate = self;
NSString *str = [NSString stringWithFormat: @"%@ %lu", @"Device: ", activePeripheral.UUID];
[self sendNotification:str];
}
//sendNotification is a func that creates a local notification for debugging when device connected to comp
当我运行测试时,当我的 BLE 设备与手机通信且应用程序不在内存中时,didFinishLaunchWithOptions 被 100% 调用,但 willRestoreState 从未被调用。
任何和所有的帮助都会很棒!谢谢!
最佳答案
好的,所以我不得不删除我对这个问题的两个答案。但我想我终于弄明白了。
This comment是你问题的关键。本质上,这个 centralManager:willRestoreState:
只有在外围设备正在进行未完成的操作时被操作系统强制关闭时才会被调用(这不包括扫描外围设备进一步调查,如果您正在扫描服务 UUID 并且应用程序以相同的方式被终止,或者您已经完成连接,它实际上会调用您的委托(delegate))。
复制: 我在我的 MacBook 上设置了一个使用 CoreBluetooth 的外围设备。我在外围设备上做广告,让我的 iPhone 上的中央设备发现它。然后,保持 OSX 外围应用程序运行,终止 Mac 上的 BT 连接,然后从 iOS 设备上的中央启动连接。这显然将持续运行,因为外围设备不可访问(显然,连接尝试可以永远持续,因为蓝牙 LE 没有连接超时)。然后,我向我的图形用户界面添加了一个按钮,并将其连接到我的 View Controller 中的一个函数:
- (IBAction)crash:(id)sender
{
kill(getpid(), SIGKILL);
}
这将终止应用程序,就像它被操作系统终止一样。尝试连接后,轻按按钮即可使应用程序崩溃(有时需要轻按两次)。
在您的 Mac 上激活蓝牙将导致 iOS 重新启动您的应用程序并调用正确的处理程序(包括 centralManager:willRestoreState:
)。
如果您想调试处理程序(通过设置断点),在 Xcode 中,在您的 Mac 上打开 BT 之前,设置一个断点,然后选择“调试 > 附加到进程... > 按进程标识符或名称”。 ..'.
在出现的对话框中,键入您的应用名称(应与您的目标相同)并单击“附加”。然后 Xcode 会在状态窗口中说等待启动。等待几秒钟,然后在 OSX 上打开 BT。确保您的外围设备仍在播放广告,然后 iOS 将拾取它并重新启动您的应用程序以处理连接。
可能还有其他方法可以对此进行测试(也许对特性使用通知?)但此流程是 100% 可重现的,因此可能会帮助您最轻松地测试您的代码。
关于ios - CoreBluetooth 状态保存问题 : willRestoreState not called in iOS 7. 1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22412376/