I have a class which I am trying to initiate, however, as the title suggests, the convenience init
method runs infinitely. Why is this?
class Peripheral: CBPeripheralManager, CBPeripheralManagerDelegate
{
var peripheralManager : CBPeripheralManager!
convenience init(delegate: CBPeripheralManagerDelegate?, queue: DispatchQueue?)
{
print("howdy")
self.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: [CBPeripheralManagerOptionShowPowerAlertKey: true])
peripheralManager.add(myCBService)
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager)
{
}
}
let myPeripheral = Peripheral.init()
I ran my program for about ten seconds, and "howdy" printed 42,266 times. I put the print statement BELOW self.init(), and "howdy" did not print at all. What am I doing wrong?
You have found a little conflict between the Objective-C and Swift implementation.
CBPeripheralManager
has 3 init
methods which basically work like this:
convenience init() {
self.init(delegate: nil, queue: nil)
}
convenience init(delegate: CBPeripheralManagerDelegate?, queue: DispatchQueue?) {
self.init(delegate: delegate, queue: queue, options: nil)
}
// designated
init(delegate: CBPeripheralManagerDelegate?, queue: DispatchQueue?, options: [String : Any]?)
// the actual implementation
}
Once you have declared a new convenience
initializer, the two convenience initializers get removed and only the one defined by you exists. Normally, you wouldn't be able to call Peripheral.init()
at all. However, the problem is that Objective-C classes always have an init
method without parameters.
That means that init()
delegates to your new convenience initializer and your initializer delegates to init()
again, ending up in an infinite loop.
Solution, don't call init()
. Call the designated initializer:
class Peripheral: CBPeripheralManager, CBPeripheralManagerDelegate {
var peripheralManager : CBPeripheralManager!
convenience init(delegate: CBPeripheralManagerDelegate?, queue: DispatchQueue?) {
print("howdy")
self.init(delegate: delegate, queue: queue, options: nil)
peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: [CBPeripheralManagerOptionShowPowerAlertKey: true])
peripheralManager.add(myCBService)
}
}
However, there seems to be a deeper problem. Why do you create a new CBPeripheralManager
from inside a CBPeripheralManager
?
Isn't what you want actually the following?:
class Peripheral: NSObject, CBPeripheralManagerDelegate {
var peripheralManager: CBPeripheralManager!
override init() {
print("howdy")
super.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: [CBPeripheralManagerOptionShowPowerAlertKey: true])
peripheralManager.add(myCBService)
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
}
}