Что вызывает CBCentralManagerStateUnknown в iOS?
Почему я получаю CBCentralManagerStateUnknown
на iPad 2 при использовании этого простого кода?
- (BOOL)viewDidLoad {
bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
if ([manager state] == CBCentralManagerStatePoweredOff) NSLog(@"CBCentralManagerStatePoweredOff");
if ([manager state] == CBCentralManagerStatePoweredOn) NSLog(@"CBCentralManagerStatePoweredOn");
if ([manager state] == CBCentralManagerStateResetting) NSLog(@"CBCentralManagerStateResetting");
if ([manager state] == CBCentralManagerStateUnauthorized) NSLog(@"CBCentralManagerStateUnauthorized");
if ([manager state] == CBCentralManagerStateUnknown) NSLog(@"CBCentralManagerStateUnknown");
if ([manager state] == CBCentralManagerStateUnsupported) NSLog(@"CBCentralManagerStateUnsupported");
}
Я не могу понять, что означает CBCentralManagerStateUnknown
. Что я делаю? Apple docs просто скажут:
Состояние неизвестно, обновление не ожидается.
Я получаю этот ответ с подключенным Bluetooth-устройством, а также когда Bluetooth выключен.
Если я попытаюсь запустить что-то вроде [manager retrieveConnectedPeripherals]
, я также получаю это сообщение в консоли:
CoreBluetooth[WARNING] <CBConcreteCentralManager: ...> is not powered on
Ответы
Ответ 1
Я знаю, почему делегат никогда не вызывается. Поскольку объект удаляется из памяти. Просто сделайте сильное свойство
@property (strong, nonatomic) DiscoverBluetoothDevices *btDevices;
И в init
@implementation DiscoverBluetoothDevices
- (id) init
{
self = [super init];
if(self) {
centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
[centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @YES}];
}
return self;
}
И теперь делегат называется правильно.
Ответ 2
CBCentralManagerStateUnknown
просто означает, что iOS запустил процесс BLE, но не завершил инициализацию. Дайте ему момент, и состояние изменится.
В общем, вы "дадите ему мгновение", обнаружив состояние изменения в обработчике делегата CBCentralManagerDelegate
, вместо того, чтобы смотреть на него сразу после вызова инициализации. Вы реализуете
- (void) centralManagerDidUpdateState: (CBCentralManager *) central;
Есть несколько хороших примеров, которые показывают это, например, Apple монитор сердечного ритма.
Ответ 3
Если центральное состояние переходит на CBCentralManagerStateUnsupported
(в то время как Bluetooth Low Energy поддерживается устройством), это скорее всего означает, что приложение сделало что-то плохое с CoreBluetooth.
Проверьте журнал iOS Bluetooth Diagnostic Logging.
Например, если вы это сделаете...
_cm1 = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"not_unique" }];
_cm2 = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"not_unique" }];
... второе центральное состояние перейдет к CBCentralManagerStateUnsupported
.
Ответ 4
Фактический ответ (старый вопрос, который я знаю); начните сканирование периферийных устройств, это запустит BT LE, и ваши делегаты получат обратный вызов. Мои делегаты и информация о штате не изменились, пока я не сделал это.
а. Настройте свой cbcentralmanager, как показано ниже.
б. У вас есть -central * делегаты в вашем коде и в вашем файле .h
с. NSLog или обновить ярлык на экране с новым статусом. И... Успех.
cManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[cManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @YES}];
Ответ 5
Вам нужно сохранить экземпляр CBCentralManager
(поместить его в ivar или private property) и дождаться, когда будет вызван делегат изменения состояния. (Состояние всегда "неизвестно", если вы проверяете его сразу после создания экземпляра менеджера. В методе делегата мгновенно появится реальное состояние.)
Ответ 6
В моем случае я использовал приложение AppDelegate в качестве делегата для
CBCentralManagerDelegate
и косвенно для
AVCaptureMetadataOutputObjectsDelegate.
за один раз.
1) Позаботьтесь о потоках. Используйте
dispatch_get_main_queue()
или
[NSThread mainThread]
для работы с BLE.
2) Позаботьтесь об использовании этих 2 делегатов на 1 объекте. Поскольку аппаратное обеспечение НЕ thead и контекст сохранить