0

This is a class where I've defined the protocol. The class I've defined the protocol in is an NSObject(if that makes any difference).

class A:

import UIKit
import CoreBluetooth

protocol deviceNameDelegate {
    func discoveredDeviceName(deviceName: String, peripheral: CBPeripheral)
}

class BlueCoreManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
...
var del: deviceNameDelegate?
...
 func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {

        if del != nil {

            let peripheralName = peripheral.name!
            let peripheralDevice = peripheral
            print("Delegate is not nil")
            del!.discoveredDeviceName(peripheralName, peripheral: peripheralDevice)

        } else {
            print("delegate is nil")
        }
...
      }
   }

class B:

import UIKit
import CoreBluetooth

class availableDevicesViewController: UIViewController, deviceNameDelegate {

    var ble = BlueCoreManager()
...
 override func viewDidLoad() {
        super.viewDidLoad()

        ble.del = self
}

func discoveredDeviceName(deviceName: String, peripheral: CBPeripheral) {
...
     }
}

I've implemented custom protocols twice before but I'm really stumped on this one. I can't seem to figure out why it isn't working. The steps I've followed:

a. I created the protocol blueprint in class A

b. Made an optional delegate variable in class A

c. Passing values at through the delegate in class A

d. Added protocol to class B and implemented function to make it conform to the protocol

e. Set the delegate from class A as self(i.e. class B)

I am still pretty new to swift, so maybe I might have missed something. Can anybody shine a light? What am I not doing?

Jobs
  • 628
  • 7
  • 27
  • protocol are used for child to parent class communications. – Gagan_iOS Jun 15 '16 at 09:47
  • so are you saying that I can't use a protocol to communicate over here? – Jobs Jun 15 '16 at 09:52
  • @Gagan_iOS what do you mean? This is a perfectly valid use of delegates. There does not need to be any specific relationship between the delegate and the delegator – Paulw11 Jun 15 '16 at 09:58
  • @jobs. I suggest you set breakpoints to see what is going on. Do you have more than one instance of `BlueCoreManager`? Is it possible that the object instance where `didDiscoverPeripheral` is being called isn't the instance where `del` is set? – Paulw11 Jun 15 '16 at 10:00
  • ok ..do one thing..create your protocol & delegate in appdelegate class. Now use your delegate. – Gagan_iOS Jun 15 '16 at 10:04
  • Does the console print ```delegate is not nil```??? – kandelvijaya Jun 15 '16 at 10:13
  • @Paulw11 in the second class, after initializing an instance of BlueCoreManager, I am calling functions within it through the singleton model eg. BlueCoreManager.shared.play() where shared is also defined as an instance of BlueCoreManager initialized within the BlueCoreManager class. Could you elaborate on your second question, I didn't quite understand – Jobs Jun 15 '16 at 10:15
  • @kandelvijaya Yup it does – Jobs Jun 15 '16 at 10:16
  • 1
    If that class is meant to be a singleton then you shouldn't initiate a new copy. You should always use `BlueCoreManager.shared()` to get the singleton instance. – Paulw11 Jun 15 '16 at 10:18
  • Just to be clear, What you are saying is ``` Class B delegate implementation ``` is not called?? – kandelvijaya Jun 15 '16 at 10:19
  • Set a breakpoint in your `didDiscoverPeripheral` method and step through; does it call the delegate? What does your delegate method do? Does it update the UI? Do you dispatch these updates onto the main queue? – Paulw11 Jun 15 '16 at 10:20
  • @kandelvijaya yes I think that is whats the issue is – Jobs Jun 15 '16 at 10:31
  • @Paulw11 It worked! It wasn't working because there were two instances of the class. I replaced everything with BlueCoreManager.shared and it runs perfect. Thanks mate! – Jobs Jun 15 '16 at 10:34

2 Answers2

1

Since your BlueCoreManager is a singleton, you shouldn't ever create an instance of it, as you do in your view controller.

You should always use BlueCoreManager.shared() to get the singleton instance.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • @ Paulw11 Can you check out this question. its also about protocols and the error is similar, the only difference is its a protocol within a uipageviewcontroller and a toolbar. the delegate shows nil. No singleton in this question. http://stackoverflow.com/questions/38330509/go-to-the-next-page-programmatically-within-a-uipageviewcontroller – Jobs Jul 13 '16 at 04:34
0

There are multiple possible causes for this:
- Call to discover peripherals is executed and peripherals are discovered before your viewDidLoad, hence the del variable is not set. Maybe it's in your BlueCoreManager init code, which is executed when availableDevicesViewController is initialzed, long before viewDidLoad is executed.
- didDiscoverPeripheral is not called at all - if some how the scan can not detect any device.

I strongly suggest you make delegate var a weak var, not just optional:
weak var del: deviceNameDelegate?
as well as use optionals the way they're intended:
del?.discoveredDeviceName(peripheralName, peripheral: peripheralDevice)

Duy Pham
  • 211
  • 1
  • 4
  • I am performing a check before del!.discoveredDeviceName(...), so it doesn't matter – Jobs Jun 15 '16 at 11:46