IOS 8 Core Bluetooth не обнаруживает периферийные устройства

У меня возникли проблемы с получением Core Bluetooth для обнаружения периферийных устройств на iOS 8. Тот же код отлично работает на устройстве iOS 7. Первоначально я думал, что это будет проблема с разрешениями, так как я выполнял некоторую работу iBeacon, и есть некоторые изменения в разрешениях Core Location на iOS 8. Я ничего не смог найти в Интернете, которые помогли с этим. Вот ссылка на образец проекта, который отлично подходит для меня на iOS 7, но не на iOS 8:

https://github.com/elgreco84/PeripheralScanning

Если я запустил этот проект на устройстве iOS 7, он будет записывать данные рекламы для нескольких устройств вокруг меня. На iOS 8 единственный вывод, который я вижу, заключается в том, что состояние центрального менеджера "включено".

Ответы

Ответ 1

Неправильно запускать сканирование периферийных устройств до тех пор, пока вы не включитесь в состояние "включено". Возможно, на вашем устройстве iOS7 вам повезло с выбором времени, но код по-прежнему неверен. Ваш centralManagerDidUpdateState: должен быть

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

    }
}

И удалите вызов scanForPeripheralsWithServices из didFinishLaunchingWithOptions

Ответ 2

Я столкнулся с той же проблемой при создании очень простого приложения для сканирования BLE. Добавлен необходимый метод "centralManagerDidUpdateState". Но ничего не получилось.

Я считаю, что проблема связана с queue. Поместите экземпляр CBCentralManager в dispatch_get_main_queue

Этот фрагмент кода делает это:

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

          }

Использование приложения запуска по умолчанию Single View xCode. Вы можете поместить это в файл 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")
            }
        }

Ответ 3

Моя связанная с этим проблема была решена путем обновления сигнатуры метода CBCentralManagerDelegate от

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

к

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

Обратите внимание на другое имя параметра didDiscover\Peripheral.

Также обратите внимание, что, поскольку это не является обязательным методом делегата, нет никаких предупреждений о том, что первая версия не была вообще связана с делегатом и, следовательно, (конечно) никогда не будет вызвана. Со всеми изменениями синтаксиса и устаревшими именами/версиями/документами/учебниками основных методов я бы хотел, чтобы у Swift был лучший способ сообщить компилятору, что вы пытаетесь использовать (действительный) метод делегирования (помимо полагаться на авто-мышление)