14

I'm having trouble getting Core Bluetooth to discover peripherals on iOS 8. Same code works fine on iOS 7 device. Initially I thought it would be a permissions issue since I had been doing some iBeacon work and there are some changes in Core Location permissions on iOS 8. I couldn't find anything online that helped with that however. Here is a link to a sample project that works fine for me on iOS 7 but not on iOS 8:

https://github.com/elgreco84/PeripheralScanning

If I run this project on an iOS 7 device it will log advertisement data for a number of devices around me. On iOS 8 the only output I see is that the Central Manager state is "Powered On".

Rick Roberts
  • 845
  • 10
  • 13
  • possible duplicate of [When would CBCentralManager's state ever be powered on but still give me a "not powered on" warning?](http://stackoverflow.com/questions/17118534/when-would-cbcentralmanagers-state-ever-be-powered-on-but-still-give-me-a-not) – Tommy Devoy Sep 01 '14 at 19:58

2 Answers2

33

It isn't valid to start scanning for peripherals until you are in the 'powered on' state. Perhaps on your iOS7 device you are lucky with timing, but the code is still incorrect. Your centralManagerDidUpdateState: should be

- (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:
        {
        }

    }
}

And remove the call to scanForPeripheralsWithServices from didFinishLaunchingWithOptions

Paulw11
  • 95,291
  • 12
  • 135
  • 153
4

I ran into the same issue while building a very basic BLE scanner app. The required method "centralManagerDidUpdateState" was added. But nothing worked.

I believe the problem is related to queue. Put the CBCentralManager instance in a dispatch_get_main_queue

This code snippet does that:

       // 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())   

          }

Using the Default Single View xCode start app. You can put this into the ViewController.swift file:

   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")
            }
        }