2012-09-20 6 views
11

Perché ottengo CBCentralManagerStateUnknown su un iPad 2 quando utilizzo questo semplice codice?Cosa causa CBCentralManagerStateSnknown in iOS?

- (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"); 

} 

Non riesco a capire che cosa significa CBCentralManagerStateUnknown. Cosa faccio? Il Apple docs basta dire:

Stato ignoto, aggiornamento imminente.

Ottengo questa risposta con un dispositivo Bluetooth collegato, e anche quando Bluetooth è spento. Se provo a eseguire qualcosa di simile [manager retrieveConnectedPeripherals], ho anche ottenere questo messaggio nella console:

CoreBluetooth[WARNING] <CBConcreteCentralManager: ...> is not powered on 
+1

Significa che lo stato è sconosciuto. In questo caso, probabilmente perché l'hardware Bluetooth non è ancora stato avviato. Qual è il problema? –

+0

Non riesco ad arrivare allo stato 'CBCentralManagerStatePoweredOn' in modo che possa fare qualsiasi cosa. Cosa devo fare per arrivare a quello stato? – woz

+0

Sono un po 'confuso. Hai detto che "ottengo questa risposta con un dispositivo Bluetooth collegato", ma hai anche indicato che non puoi fare nulla. Come hai il dispositivo connesso in primo luogo, quindi? – yuklai

risposta

15

So perché il delegato non viene mai chiamato. Perché l'oggetto viene cancellato dalla memoria. Basta fare una proprietà forte

@property (strong, nonatomic) DiscoverBluetoothDevices *btDevices;

E in 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; 
} 

E ora delegare si chiama correttamente.

+0

Provare a cambiare il codice da [self.manager scanForPeripheralsWithServices: [NSArray arrayWithObject: [CBUUID UUIDWithString: @ "180D"]] options: nil]; con NSDictionary * dictionary = [Dizionario NSDictionaryWithObject: [NSNumber numberWithBool: YES] forKey: CBCentralManagerScanOptionAllowDuplicatesKey]; [self.manager scanForPeripheralsWithServices: nil options: dictionary]; – york

+2

Perché? Il mio codice funziona bene :) –

2

CBCentralManagerStateUnknown significa semplicemente iOS ha avviato il processo di BLE, ma non ha completato l'inizializzazione. Dagli un attimo e lo stato cambierà.

In generale, è possibile "dargli un momento" rilevando un cambiamento di stato in un gestore di delegati CBCentralManagerDelegate anziché esaminarlo subito dopo la chiamata di inizializzazione. Si implementare

- (void) centralManagerDidUpdateState: (CBCentralManager *) central; 

Ci sono alcuni buoni esempi che dimostrano questo, come Apple di heart rate monitor.

+3

Ho un punto di interruzione in quella funzione, ma la funzione non viene mai chiamata. – woz

+0

Ho lo stesso problema che centralManagerDidUpdateState non viene mai chiamato – Warewolf

+1

A seconda di cosa si sta facendo fino a questo punto, una cosa che si potrebbe provare è il riavvio del dispositivo iOS. Ho visto iOS confondersi con i collegamenti BLE in passato, generalmente quando si utilizzano più app per connettersi a un singolo dispositivo. Il riavvio del dispositivo è spesso l'unica cosa che sembra chiarire il problema. – Mike

1

La risposta effettiva (vecchia domanda che conosco); avvia una scansione per periferiche, questo avvierà BT LE in su e i tuoi delegati verranno richiamati. I miei delegati e le informazioni sullo stato non sono cambiati fino a quando non l'ho fatto.

a. Imposta il tuo cbcentralmanager come sotto b. Avere i delegati -central * nel codice e nel file .h c. NSLog o avere un'etichetta sullo schermo di aggiornamento con nuovo stato. E ... successo.

cManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; 

[cManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @YES}]; 
+0

Questa risposta è sufficiente per ottenere questo risultato. – d2burke

1

È necessario conservare l'istanza CBCentralManager (inserirla in una proprietà privata o ivar) e attendere la chiamata del delegato di modifica dello stato. (Lo stato è sempre "sconosciuto" se lo si controlla immediatamente dopo l'istanziazione del gestore. Lo stato reale apparirà momentaneamente nel metodo delegato.)

2

Se lo stato di una centrale passa a CBCentralManagerStateUnsupported (mentre Bluetooth Low Energy è supportato dal dispositivo) molto probabilmente significa che l'app ha fatto qualcosa di male con CoreBluetooth.

Controllare i registri iOS Bluetooth Diagnostic Logging.

Ad esempio, se si esegue questa operazione ...

_cm1 = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"not_unique" }]; _cm2 = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"not_unique" }];

... lo stato del secondo centrale andrà a CBCentralManagerStateUnsupported.

0

Nel mio caso ho usato AppDelegate come delegato per

CBCentralManagerDelegate 

e indirectional per

AVCaptureMetadataOutputObjectsDelegate. 

in una volta.

1) Fare attenzione alle filettature. Utilizzare

dispatch_get_main_queue() 

o

[NSThread mainThread] 

per il lavoro con BLE.

2) Prestare attenzione all'utilizzo di questo 2 delegati su 1 oggetto. Perché l'hardware è NOT thead e context save