2014-08-30 14 views
14

Sto riscontrando problemi nell'ottenere Core Bluetooth per rilevare periferiche su iOS 8. Lo stesso codice funziona correttamente sul dispositivo iOS 7. Inizialmente pensavo che sarebbe stato un problema di permessi visto che stavo facendo un po 'di lavoro su iBeacon e ci sono alcuni cambiamenti nelle autorizzazioni di Core Location su iOS 8. Non sono riuscito a trovare nulla online che mi aiutasse comunque. Ecco un link ad un progetto di esempio che funziona bene per me su iOS 7, ma non su iOS 8:iOS 8 Core Bluetooth non rileva le periferiche

https://github.com/elgreco84/PeripheralScanning

Se eseguo questo progetto su un dispositivo iOS 7 che verrà registrare i dati pubblicità per un certo numero di dispositivi intorno a me. Su iOS 8 l'unico risultato che vedo è che lo stato di Central Manager è "Acceso".

+0

possibile duplicato di [Quando lo stato di CBCentralManager dovrebbe essere acceso ma mi viene comunque visualizzato un avviso "non acceso"?] (Http://stackoverflow.com/questions/17118534/when-would-cbcentralmanagers-state-ever- be-powered-on-but-still-give-me-a-not) –

risposta

30

Non è valido avviare la scansione delle periferiche finché non si è nello stato "acceso". Forse sul tuo dispositivo iOS7 sei fortunato con i tempi, ma il codice è ancora errato. Il tuo centralManagerDidUpdateState: dovrebbe essere

- (void)centralManagerDidUpdateState:(CBCentralManager *)central 
{ 
    switch (central.state) 
    { 
     case CBCentralManagerStateUnsupported: 
     { 
      NSLog(@"State: Unsupported"); 
     } break; 

     case CBCentralManagerStateUnauthorized: 
     { 
      NSLog(@"State: Unauthorized"); 
     } break; 

     case CBCentralManagerStatePoweredOff: 
     { 
      NSLog(@"State: Powered Off"); 
     } break; 

     case CBCentralManagerStatePoweredOn: 
     { 
      NSLog(@"State: Powered On"); 
      [self.manager scanForPeripheralsWithServices:nil options:nil]; 
     } break; 

     case CBCentralManagerStateUnknown: 
     { 
      NSLog(@"State: Unknown"); 
     } break; 

     default: 
     { 
     } 

    } 
} 

e rimuovere la chiamata a scanForPeripheralsWithServices da didFinishLaunchingWithOptions

+2

Grazie mille. Mi hai salvato dal buttare la mia HRM fuori dalla finestra. – Craimasjien

+0

Ho fatto esattamente questo, ma ancora a volte, non tutte le volte, 'didDiscoverPeripheral' non viene chiamato affatto -_- davvero confuso .. – Zennichimaro

+0

ma per me, la sua chiamata ha fatto il metodo DiscoverSceripheral molto molto recentemente in iOS 8, come aggiustalo? –

4

Ho incontrato lo stesso problema mentre la costruzione di un applicazione molto semplice scanner BLE. È stato aggiunto il metodo richiesto "centralManagerDidUpdateState". Ma niente ha funzionato.

Credo che il problema sia relativo a queue. Mettere l'istanza CBCentralManager in un frammento dispatch_get_main_queue

Questo codice lo fa:

 // BLE Stuff 
      let myCentralManager = CBCentralManager() 

     // Put CentralManager in the main queue 
     required init(coder aDecoder: NSCoder) { 
      super.init(coder: aDecoder) 
      myCentralManager = CBCentralManager(delegate: self, queue: dispatch_get_main_queue()) 

      } 

Utilizzando il default Singolo View xCode inizio app. Si può mettere questo nel file ViewController.swift:

import UIKit 
    import CoreBluetooth  

    class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { 


     // BLE Stuff 
     let myCentralManager = CBCentralManager() 
     var peripheralArray = [CBPeripheral]() // create now empty array. 


     // Put CentralManager in the main queue 
     required init(coder aDecoder: NSCoder) { 
      super.init(coder: aDecoder) 
      myCentralManager = CBCentralManager(delegate: self, queue: dispatch_get_main_queue()) 

     } 



     override func viewDidLoad() { 
      super.viewDidLoad() 
      // Do any additional setup after loading the view, typically from a nib. 

     } 


     override func didReceiveMemoryWarning() { 
      super.didReceiveMemoryWarning() 
      // Dispose of any resources that can be recreated. 
     } 

     // Mark CBCentralManager Methods 

     func centralManagerDidUpdateState(central: CBCentralManager!) { 

      updateStatusLabel("centralManagerDidUpdateState") 


      switch central.state{ 
      case .PoweredOn: 
       updateStatusLabel("poweredOn") 


      case .PoweredOff: 
       updateStatusLabel("Central State PoweredOFF") 

      case .Resetting: 
       updateStatusLabel("Central State Resetting") 

      case .Unauthorized: 
       updateStatusLabel("Central State Unauthorized") 

      case .Unknown: 
       updateStatusLabel("Central State Unknown") 

      case .Unsupported: 
       println("Central State Unsupported") 

      default: 
       println("Central State None Of The Above") 

      } 

     } 

     func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) { 
        println("Did Discover Peripheral") 
      } 
     } 
1

Il mio problema correlato è stato risolto aggiornando la firma CBCentralManagerDelegate metodo dal

func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) 

a

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) 

Nota il nome diverso di il parametro didDiscover\Peripheral.

Inoltre, poiché questo non è un metodo delegato richiesto, non vi è alcun avviso sul fatto che la prima versione non è stata affatto collegata al delegato e, quindi (ovviamente), non verrebbe mai chiamata. Con tutte le modifiche alla sintassi e nomi/versioni/documentazioni/tutorial dei metodi Core obsoleti, vorrei che Swift avesse un modo migliore di dire al compilatore che stai cercando di usare un metodo (valido) delegato (oltre a fare affidamento su Auto-thinkletion)

Problemi correlati