self.init() 无限地导致便利 init(){ } 到 运行

self.init() causes convenience init(){ } to run infinitely

我有一个 class 正在尝试启动,但是,正如标题所示,convenience init 方法会无限运行。这是为什么?

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()

我运行我的程序大约十秒钟,“你好”打印了42,266次。我将打印语句放在 self.init() 下方,而“howdy”根本没有打印出来。我做错了什么?

您发现 Objective-C 和 Swift 实现之间存在一点冲突。

CBPeripheralManager 有 3 个 init 方法,它们基本上是这样工作的:

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
}

一旦你声明了一个新的 convenience 初始化器,两个便利的初始化器就会被删除,只有你定义的那个存在。通常,您根本无法调用 Peripheral.init()。但是,问题是 Objective-C 类 总是 有一个没有参数的 init 方法。

这意味着 init() 委托给您的新便利初始化器,您的初始化器再次委托给 init(),以无限循环结束。

解决方法,不要调用init()。调用指定的初始化器:

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)
    }
}

不过,似乎还有更深层次的问题。为什么要从 CBPeripheralManager 中创建一个新的 CBPeripheralManager

你要的不正是下面这个吗?:

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) {
    }
}