CoreBluetooth状态保存问题:在iOS 7.1中未调用willRestoreState

coo*_*459 9 iphone bluetooth objective-c ios

CoreBluetooth状态保存问题:在iOS 7.1中未调用willRestoreState

大家好.过去几周我一直致力于蓝牙LE项目,并遇到了障碍.我无法在iOS 7/7.1中正常恢复状态.我遵循了(我认为)Apple提出的所有步骤,并在其他堆栈溢出帖子上获得了一些线索.

  1. 我为plist添加了正确的蓝牙权限
  2. 当我创建我的中央管理器时,我给它一个恢复标识符键.
  3. 我总是使用相同的密钥来实例化CM
  4. 我将willRestoreState函数添加到CM委托

我的测试用例:

  1. 连接到外围设备
  2. 确认连接
  3. 模拟内存驱逐(kill(getpid(),SIGKILL);)
  4. 传输数据

结果iOS 7:

应用程序将在AppDelegate didFinishLaunchingWithOptions函数中响应,但是launchOptions [UIApplicationLaunchOptionsBluetoothCentralsKey]内部的NSArray内容始终是一个空数组.

iOS 7.1上的结果:

进展!我可以在100%的时间内在UIApplicationLaunchOptionsBluetoothCentralsKey数组中看到我的CentralManager密钥,但永远不会调用fromRestoreState.

码:

//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
Run Code Online (Sandbox Code Playgroud)

当我运行测试时,当应用程序不在内存中时,当我的BLE设备与手机通信时,didFinishLaunchWithOptions被调用100%,但永远不会调用willRestoreState.

任何和所有的帮助都会很棒!谢谢!

San*_*man 15

好的,所以我不得不删除我对这个问题的两个答案.但我想我终于搞清楚了.

此评论是您的问题的关键.从本质上讲,centralManager:willRestoreState:只有在操作系统关闭时才会调用此操作,而外围设备正在执行未完成的操作(这不包括扫描外围设备 在进一步调查中,如果您正在扫描服务UUID并且应用程序以相同的方式被终止,或者您已经完成连接,那么它实际上会调用您的代理人).

复制:我在MacBook上使用CoreBluetooth设置外围设备.我在外围设备上做广告,让我的iPhone上的中心发现它.然后,让OSX外围设备应用程序继续运行,终止Mac上的BT连接,然后从iOS设备的中央启动连接.这显然将继续运行,因为外围设备是不可达的(显然,连接尝试可以永久持续,因为蓝牙LE在连接上没有超时).然后我给我的gui添加了一个按钮,并将它连接到我的视图控制器中的一个函数:

- (IBAction)crash:(id)sender
{
    kill(getpid(), SIGKILL);
}
Run Code Online (Sandbox Code Playgroud)

这将杀死应用程序,好像它被操作系统杀死一样.一旦您尝试连接,请点按该按钮以使应用程序崩溃(有时需要两次点击).

在Mac上激活蓝牙将导致iOS重新启动您的应用并调用正确的处理程序(包括centralManager:willRestoreState:).

如果要调试处理程序(通过设置断点),在Xcode中,在Mac上打开BT之前,设置断点然后选择"Debug> Attach to Process ...> By Process Identifier or Name ..." .

在显示的对话框中,键入应用程序的名称(应与目标相同),然后单击"附加".然后Xcode将在状态窗口中等待启动.等待几秒钟然后在OSX上打开BT.确保您的外围设备仍然是广告,然后iOS将接收它并重新启动您的应用程序以处理连接.

有可能有其他方法来测试这个(使用特征上的通知可能?)但这个流程是100%可重复的,所以可能会帮助您最容易地测试代码.


aka*_*aru -2

您还需要使用恢复标识符实例化您的外围设备。