Быстрая простая проблема "Использование неразрешенного идентификатора" - PullRequest
0 голосов
/ 20 июня 2020

Я новичок в языке программирования Swift, у меня ошибка в простой программе, я пытаюсь подключить свое приложение ios к одному модулю Bluetooth HM-10.

Я прикрепил изображение с моим код и ошибка

код и ошибка

Спасибо большое, ребята! Надеюсь, однажды я отвечу здесь.

1 Ответ

0 голосов
/ 20 июня 2020

Как указывали другие, следует избегать использования глобальных переменных. Если вы сделаете его свойством какого-то класса, это позволит избежать проблемы.

FWIW, проблема, строго говоря, не в использовании глобального, а скорее в конкретном имени переменной, которое вы выбрали. Например, измените имя этой глобальной переменной, она компилируется нормально:

import UIKit
import CoreBluetooth

var manager: CBCentralManager!

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        manager = CBCentralManager(delegate: self, queue: nil)
    }
}

extension ViewController: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            print("BLE powered on")
        } else {
            print("Something wrong with BLE")
        }
    }
}

Проблема в том, что у компилятора есть проблемы с разрешением этого глобального символа, centralManager, при наличии нескольких методов протокола то же имя (например, centralManager(_:didConnect:), centralManager(_:didDisconnectPeripheral:error:), и т. д. c.). Можно было бы ожидать, что компилятор сможет устранить неоднозначность между глобальными методами и методами протокола с учетом контекста, но это не так. (Эту проблему можно также выявить, определив глобальный контроллер с именем tableView в представлении, который соответствует UITableViewDataSource.)

В итоге техническая проблема заключается в выборе имени глобальной переменной. Но правильный ответ - это вообще не должно быть глобальным.

Как только у вас возникнут непосредственные проблемы, вы можете пересмотреть, стоит ли вообще помещать этот код Bluetooth в контроллер представления. Конечно, в простых демонстрационных приложениях мы часто будем использовать подобные ярлыки, но по мере роста вашего приложения контроллер представления станет громоздким. Кроме того, в конечном итоге вы захотите добавить функции Bluetooth к другим контроллерам представления, и вы собираетесь дублировать код.

Вместо этого создайте свой собственный класс менеджера, абстрагируя детали CBCentralManager и CBPeripheral вдали от контроллеров просмотра. Затем вы можете предоставить своим контроллерам представления красивый простой интерфейс для взаимодействия с менеджером.

Например, у вас может быть что-то вроде:

class BluetoothManager: NSObject {
    var isAvailableHandler: ((Bool) -> Void)?
    
    private var manager: CBCentralManager? = nil
    
    override init() {
        super.init()
    }
    
    func start() {
        guard manager == nil else { return }
        
        manager = CBCentralManager(delegate: self, queue: nil)
    }
}

extension BluetoothManager: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        isAvailableHandler?(central.state == .poweredOn)
    }
}

И тогда вы можете делать такие вещи, как :

class ViewController: UIViewController {
    private let deviceManager = BluetoothManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        deviceManager.isAvailableHandler = { [weak self] isAvailable in
            print(isAvailable ? "Powered on" : "Not available")
        }
        
        deviceManager.start()
    }
}

Теперь в этом примере я обрабатываю только centralManagerDidUpdateState, но вы бы добавили дополнительные замыкания или свой собственный протокол для обработки любых событий, которые вы хотите предоставить своим контроллерам представления. Но, надеюсь, это иллюстрирует идею.

...