Until now the iPhone has paired to a bluetooth device when the app is opened, but I want to pair with a button click instead. I tried to put all the scanning and connection functions in a IBAction, but nothing happens when I push the button. In the first function after the IBAction I have a print output to check if it even enters the function, but I don't get the print. I also tried to put a delay after the manager.scanForPeripherals but didn't work either. What am I missing here? anyone know? Thanks for any replies! here is my code (without the delay):
var manager: CBCentralManager!
var device: CBPeripheral?
var characteristics: [CBCharacteristic]?
var serviceUUID = "1234"
var char1 = "FFE1"
let deviceName = "HMSoft"
var connected = CBPeripheralState.connected
var disconnected = CBPeripheralState.disconnected
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
manager = CBCentralManager(delegate: self, queue: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn: break
// manager.scanForPeripherals(withServices: nil, options: nil)
case .unknown: break
case .resetting: break
case .unsupported: break
case .unauthorized: break
case .poweredOff:
break
}
}
@IBAction func connectBluetooth(_ sender: Any) {
manager.scanForPeripherals(withServices: nil, options: nil)
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
if peripheralName == self.deviceName {
// save a reference to the sensor tag
self.device = peripheral
self.device!.delegate = self
// Request a connection to the peripheral
self.manager.connect(self.device!, options: nil)
print("Check")
}
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.discoverServices(nil)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if error != nil {
return
}
if let services = peripheral.services {
for service in services {
if (service.uuid == CBUUID(string: serviceUUID)) {
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
device = peripheral
characteristics = service.characteristics
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
if error != nil {
return
}
}
}
When you initialise the CBCentralManager
and set its delegate
, the delegate will start receiving events.
So, if you only want the CBCentralManager
to be active once the user has tapped a button, rather than as soon as the screen loads, the minimum you have to do is move the code that initialises the manager
from viewDidLoad
to the button action.
So:
Move manager = CBCentralManager(delegate: self, queue: nil)
from viewDidLoad
to @IBAction func connectBluetooth(_ sender: Any)
,
Remove the call to scanForPeripherals
from the IBAction
, and;
Uncomment // manager.scanForPeripherals(withServices: nil, options: nil)
in centralManagerDidUpdateState
.