Контроллер Bluetooth отображает несколько версий устройства — Swift 3.1

У меня возникают проблемы со сканированием устройств Bluetooth в приложении, которое я создаю в рамках группового проекта. Код представления выглядит следующим образом:

import UIKit
import CoreBluetooth

class bluetoothConnectViewController: UIViewController, UITableViewDelegate, CBCentralManagerDelegate, UITableViewDataSource {

    //-----------------------
    // MARK: Variables
    //-----------------------

    var centralManager: CBCentralManager?
    var peripherals = Array<CBPeripheral>()

    //-----------------------
    // MARK: Outlets
    //-----------------------

    @IBOutlet weak var tableView: UITableView!

    //-----------------------
    // MARK: Core Functions
    //-----------------------

    override func viewDidLoad() {
        super.viewDidLoad()

        //Initialise CoreBluetooth Central Manager
        centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main, options: nil)

        // Table pull to refresh
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: #selector(refresh(_:)), for: .valueChanged)

        tableView.refreshControl = refreshControl

        tableView.delegate = self
        tableView.dataSource = self
    }

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

    //-----------------------
    // MARK: Custom Functions
    //-----------------------

    func refresh(_ refreshControl: UIRefreshControl) {
        // Do your job, when done:
        refreshControl.endRefreshing()
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return peripherals.count
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "Connect to device"
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell  = tableView.dequeueReusableCell(withIdentifier: "cell")

        if cell == nil {
            cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
        }

        let peripheral = peripherals[indexPath.row]
        cell?.textLabel?.text = peripheral.name

        return cell!
    }

    //-----------------------
    // MARK: BLE Functions
    //-----------------------

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if (central.state == .poweredOn){
            self.centralManager?.scanForPeripherals(withServices: nil, options: nil)
        }
        else {
            let alert = UIAlertController(title: "Bluetooth not enabled", message: "Enable bluetooth to scan for devuices", preferredStyle: .actionSheet)

            alert.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))
            alert.addAction(UIAlertAction(title: "Settings", style: .default, handler: { (UIAlertAction) in
                let url = URL(string: "prefs:root=Bluetooth")!
                UIApplication.shared.open(url, options: [:], completionHandler: nil)

            }))
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        peripherals.append(peripheral)
        tableView.reloadData()
    }
}

Это дает мне следующий результат при сканировании с использованием Bluetooth

UITableView отображает устройства Bluetooth

Иногда он будет отображать мой ноутбук только один раз, но это происходит с перерывами, пожалуйста, дайте мне знать, что я делаю неправильно?


person jb167897    schedule 12.04.2017    source источник
comment
Кажется, вы добавляете тот же объект CBPeripheral в массив периферийных устройств. Вы должны сравнить свойство идентификатора объекта CBPeripheral, полученное в методе didDiscover, со свойством идентификатора объектов CBPeripheral в массиве.   -  person Aravind Bhuvanendran    schedule 12.04.2017
comment
Здесь описана та же проблема: «почему corebluetooth снова и снова обнаруживает одно и то же периферийное устройство»> stackoverflow.com/questions/43351664/ Агрессивная реклама.   -  person Larme    schedule 13.04.2017


Ответы (3)


В методе didDiscover каждый раз вам нужно сравнивать CDUUID, который является свойством CBPeripheral, которое уже доступно в периферийном массиве. если не существует, вам нужно вставить в массив, иначе оставьте его.

вы получили CBUUID, используя эту строку CBUUID *uuid = периферия.UUID; и вы проверяете, этот uuid уже существует в массиве или нет.

person Bhavik Patel    schedule 12.04.2017

Периферийные устройства будут продолжать передавать данные, поэтому метод делегата centralManager(_:didDiscover:advertisementData:rssi:) будет получать несколько раз.

Чтобы решить эту проблему, вы можете заменить тип peripherals на Set или определить, было ли включено периферийное устройство перед добавлением

person Zhang    schedule 12.04.2017
comment
Я бы проверил периферийный идентификатор на уникальность, а не предполагал, что существует сопоставление 1: 1 экземпляров CBPeripheral с обнаруженными устройствами. Я считаю, что фреймворк может дать вам разные экземпляры для одного и того же устройства. - person CuriousRabbit; 13.04.2017

Кажется, что тот же объект CBPeripheral снова вставляется в периферийный массив.

Вы должны сравнить свойство идентификатора объекта CBPeripheral, полученное в методе didDiscover, со свойством идентификатора объектов CBPeripheral в массиве периферийных устройств перед добавлением.

person Aravind Bhuvanendran    schedule 12.04.2017