【问题标题】:Swift simple problem "Use of unresolved identifier"Swift 简单问题“使用未解析的标识符”
【发布时间】:2020-10-10 20:31:43
【问题描述】:

我是 Swift 编程语言的新手,我在一个简单的程序中出错,我正在尝试将我的 ios 应用程序连接到一个 HM-10 蓝牙模块。

我在图片中附上了我的代码和错误

非常感谢你们,伙计们!我希望有一天我会在这里回答。

【问题讨论】:

  • 将代码和错误信息以文本形式发布。
  • 强烈建议您不要在类或结构之外声明变量。把它们放到课堂上,它就解决了你的问题。
  • 非常感谢!你是对的,我想我错过了教程中的这一点。祝你有美好的一天!
  • @pntandrei - 下次,除了将代码作为文本包含在内,如果您在使用教程时遇到问题,请在您的问题中包含指向它的链接。

标签: ios swift bluetooth bluetooth-lowenergy core-bluetooth


【解决方案1】:

正如其他人指出的那样,应该避免使用全局变量。如果你把它作为某个类的属性,就可以避免这个问题。

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(_:didConnect:)centralManager(_:didDisconnectPeripheral:error:) 等)的情况下,编译器在解析这个全局符号 centralManager 时遇到问题。人们会期望编译器能够在给定上下文的情况下消除全局方法和协议方法之间的歧义,但事实并非如此。 (也可以通过在符合UITableViewDataSource 的视图控制器中定义一个名为tableView 的全局变量来体现这个问题。)

归根结底,技术问题是全局变量名的选择。但正确的答案是它根本不应该是全局的。


一旦你解决了眼前的问题,你可能会重新考虑是否将这个蓝牙代码放在视图控制器中。当然,在简单的演示应用程序中,我们经常会采用这样的捷径,但是随着应用程序的增长,视图控制器会变得笨拙。此外,您最终会希望将蓝牙功能添加到其他视图控制器,并且您将复制代码。

相反,创建自己的管理器类,将CBCentralManagerCBPeripheral 的细节从视图控制器中抽象出来。然后,您可以为您的视图控制器提供一个很好的简单界面,用于与管理器进行交互。

例如,你可能有类似的东西:

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,但是你需要添加额外的闭包或者你自己的协议来处理你想要暴露给你的视图控制器的任何事件。但希望这能说明这个想法。

【讨论】:

    猜你喜欢
    • 2016-04-29
    • 1970-01-01
    • 2015-05-13
    • 2016-11-28
    • 2015-05-25
    • 2017-01-28
    • 2015-11-27
    • 1970-01-01
    相关资源
    最近更新 更多