I am working on an app that reacts on disconnects of peripherals and I am now trying to adopt the ne state preservation and restoration introduced in iOS 7.
I did everything like the documentation says, means:
I added the background mode for centrals.
I always instantiate my central manager with the same unique
identifier.
I implemented the centralManager:willRestoreState:
method.
When my App moves to background I kill it in the AppDelegate callback with an kill(getpid(), SIGKILL);
. (Core Bluetooth State Preservation and Restoration Not Working, Can't relaunch app into background)
When I now disconnect a peripheral by removing the battery my app is being waked up as expected and launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey]
contains the correct identifier BUT the centralManager:willRestoreState:
was not called.
Only if I disconnect another peripheral this method gets called.
This is how I have it:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSArray *peripheralManagerIdentifiers = launchOptions[UIApplicationLaunchOptionsBluetoothPeripheralsKey];
if (peripheralManagerIdentifiers) {
// We've restored, so create the _manager on the main queue
_manager = [[CBPeripheralManager alloc] initWithDelegate:self
queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
options:@{CBPeripheralManagerOptionRestoreIdentifierKey:@"YourUniqueIdentifier"}];
} else {
// Not restored so just create as normal
manager = [[CBPeripheralManager alloc] initWithDelegate:self
queue:nil
options:@{CBPeripheralManagerOptionRestoreIdentifierKey:@"YourUniqueIdentifier"}];
}
return YES;
}
And then:
- (void)peripheralManager:(CBPeripheralManager *)peripheral
willRestoreState:(NSDictionary *)dict
{
// This is the advertisement data that was being advertised when the app was terminated by iOS
_advertisementData = dict[CBPeripheralManagerRestoredStateAdvertisementDataKey];
NSArray *services = dict[CBPeripheralManagerRestoredStateServicesKey];
// Loop through the services, I only have one service but if you have more you'll need to check against the UUID strings of each
for (CBMutableService *service in services) {
_primaryService = service;
// Loop through the characteristics
for (CBMutableCharacteristic *characteristic in _primaryService.characteristics) {
if ([characteristic.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID]) {
_primaryCharacteristic = characteristic;
NSArray *subscribedCentrals = characteristic.subscribedCentrals;
// Loop through all centrals that were subscribed when the app was terminated by iOS
for (CBCentral *central in subscribedCentrals) {
// Add them to an array
[_centrals addObject:central];
}
}
}
}
}