I am new to Swift programming language, I have an error at a simple program, I am trying to connect my ios app at one HM-10 Bluetooth module.
I attached the image with my code and the error
Thank you very much, guys. I hope one day I will be the one which answers here.
As others have pointed out, one should avoid using globals. If you make it a property of some class, that avoids the problem.
FWIW, the problem isn't, strictly speaking, the use of the global, but rather the particular variable name you chose. For example, change the name of that global variable, it compiles fine:
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")
}
}
}
The problem is that the compiler has problems resolving this global symbol, centralManager
, in the presence of multiple protocol methods of the same name (eg, centralManager(_:didConnect:)
, centralManager(_:didDisconnectPeripheral:error:)
, etc.). One would have expected the compiler to be able to disambiguate between the global and the protocol methods given the context, but it doesn't. (One can also manifest this problem by defining a global called tableView
in view controller that conforms to UITableViewDataSource
.)
Bottom line, the technical problem is the choice of global variable name. But the correct answer is that it shouldn't be a global at all.
Once you have your immediate issues behind you, you might reconsider whether to put this Bluetooth code in the view controller at all. Sure, in simple demo apps, we will often take shortcuts like that, but as your app grows, the view controller is going to become unwieldy. Also, you're eventually going to want to add Bluetooth features to other view controllers, and you're going to duplicate code.
Instead, make your own manager class, abstracting the details of CBCentralManager
and CBPeripheral
away from the view controllers. You can then provide then provide your view controllers a nice simple interface for interacting with the manager.
For example, you might have something like:
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)
}
}
And then you can do things like:
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()
}
}
Now, in this example, I'm only handling centralManagerDidUpdateState
, but you'd add additional closures or your own protocol to handle whatever events you want to expose to your view controllers. But hopefully this illustrates the idea.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.