user5308141 user5308141 - 5 months ago 30
Swift Question

Delegates not working

I'm writing code to connect to BLE devices and then list them in a table to connect or disconnect from them. I'm happy with the peripheral and manager roles and understand how to access the BLE device. Previously I've used NSNotifications but would rather ruse delegates to manage notification.

My code below is simple, in terms that it scans for devices and then prompts a delegate, but the delegate is not responding.

Please help...

Delegate

import UIKit
import CoreBluetooth

protocol BLEDelegate {

func bleDidConnectToPeripheral(sender: BLEDiscovery, peripheral: CBPeripheral)

}

let bleDiscoverySharedInstance = BLEDiscovery()

//MARK: - UUIDS for StingRay Genessis M (SRG)
let StingRayGenesisMUUID = CBUUID (string: "346D0000-12A9-11CF-1279-81F2B7A91332") //Core UUID


//MARK: - UUIDS for StingRay Genessis HR (SRG)
let StingRayGenesisHRUUID = CBUUID (string: "F9AB0000-3F75-4668-9BAC-F8264DAE7820") //Core UUID

//MARK: - Device and Characteristic Registers
var BLEDevices : [CBPeripheral] = [] //Device Array
var BLECharDictionary = [String: CBCharacteristic]() //Characteristic Dictionary


class BLEDiscovery: NSObject, CBCentralManagerDelegate {

private var centralManager : CBCentralManager?

var delegate: BLEDelegate?

override init() {
super.init()

let centralStingRayBLEQueue = dispatch_queue_create("com.stingray", DISPATCH_QUEUE_SERIAL)
centralManager = CBCentralManager(delegate: self, queue: centralStingRayBLEQueue)


}

// MARK: - CB centralManager
func centralManagerDidUpdateState(central: CBCentralManager) {
switch (central.state) {

case CBCentralManagerState.PoweredOff:
print("CBCentralManagerState.PoweredOff")

case CBCentralManagerState.Unauthorized:
// Indicate to user that the iOS device does not support BLE.
print("CBCentralManagerState.Unauthorized")
break

case CBCentralManagerState.Unknown:
// Wait for another event
print("CBCentralManagerState.Unknown")
break

case CBCentralManagerState.PoweredOn:
print("CBCentralManagerState.PoweredOn")
self.startScanning()

case CBCentralManagerState.Resetting:
print("CBCentralManagerState.Resetting")

case CBCentralManagerState.Unsupported:
print("CBCentralManagerState.Unsupported")
break
}
}

// MARK: - Start scanning for StringRay devices with the appropriate UUID
func startScanning() {
if let central = centralManager {
central.scanForPeripheralsWithServices([StingRayGenesisMUUID,StingRayGenesisHRUUID], options: nil)
}
}

// MARK: - CB Central Manager - Did discover peripheral (follows : startScanning)
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {

delegate?.bleDidConnectToPeripheral(self, peripheral: peripheral)

//Check if new discovery and append to BLEDevices where required
if BLEDevices.contains(peripheral) {
print("didDiscoverPeripheral - ALREADY DISCOVERED ==", peripheral.name)
}
else{
BLEDevices.append(peripheral)
print("didDiscoverPeripheral - NEW DISCOVERY ==", peripheral.name)
}
}

// MARK: - CB Central Manager - Connect and Disconnet BLE Devices

func connectBLEDevice (peripheral: CBPeripheral){
//Connect
self.centralManager!.connectPeripheral(peripheral, options: nil)
}

func disconnectBLEDevice (peripheral: CBPeripheral){
//Disconnect
self.centralManager?.cancelPeripheralConnection(peripheral)
}



}


Delegator

import UIKit
import CoreBluetooth

class MainViewController: UIViewController,UITableViewDelegate,UITableViewDataSource, BLEDelegate {


//MARK: - View Object Links
@IBOutlet weak var deviceTableView: UITableView!
@IBOutlet weak var infoBlockView: UIView!

// MARK: - Interface Builder Inspectables
@IBInspectable var BorderWidth : CGFloat = 0.75
@IBInspectable var BorderRadius : CGFloat = 5.0
@IBInspectable var BorderColor : UIColor = UIColor.whiteColor()

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
formatDeviceTableView()
formatInFoBlock()

}

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


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/

func bleDidConnectToPeripheral(sender: BLEDiscovery, peripheral: CBPeripheral) {
print ("Its alive == ", peripheral.name)
}

// MARK: - View Fomrating

func formatInFoBlock(){
infoBlockView.layer.borderColor = BorderColor.CGColor
infoBlockView.layer.cornerRadius = BorderRadius
infoBlockView.layer.borderWidth = BorderWidth
}


// MARK: - TableView Functions

func formatDeviceTableView() {

deviceTableView.layer.borderColor = BorderColor.CGColor
deviceTableView.layer.cornerRadius = BorderRadius
deviceTableView.layer.borderWidth = BorderWidth

}

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

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

//Define a cell and assign it to DeviceTableCellTableViewCell class and use the reuse identifier from IB - "deviceCell"
let cell = deviceTableView.dequeueReusableCellWithIdentifier("deviceCell") as! DeviceTableCellTableViewCell

cell.backgroundColor = UIColor.clearColor()
cell.deviceNameLabel.text = String(indexPath.row)

return cell

}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Row Selected ::", indexPath.row)
}

func tableView(tableView: UITableView, accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath) {
print("Accesory Selected ::", indexPath.row)
}


}


I expect the code just to print out "Its alive..." to show me that it is working...

Answer
  1. In the Delegate file in var delegate: BLEDelegate?; try to add "weak" to it:

weak var delegate: BLEDelegate?;

  1. Move let bleDiscoverySharedInstance = BLEDiscovery(); from the delegate to the delegator.

  2. To finish add: bleDiscoverySharedInstance.delegate = self;in the viewDidLoad to let it know that is the delegate.

If you want in the following link you have a really similar example to follow using a delegate: https://gitlab.com/vicrius/flickrVisualizer/tree/master

Hope all that helps.