self.init() 导致便利 init() 无限运行
Posted
技术标签:
【中文标题】self.init() 导致便利 init() 无限运行【英文标题】:self.init() causes convenience init() to run infinitelyself.init() 导致便利 init() 无限运行 【发布时间】:2020-08-18 17:25:12 【问题描述】:我有一个我正在尝试启动的课程,但是,正如标题所示,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() 的下面,“你好”根本没有打印出来。我做错了什么?
【问题讨论】:
【参考方案1】:您发现 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)
【讨论】:
感谢@Sulthan 的帮助。您的彻底回答为我消除了很多困惑,但是我按照说明进行操作,它告诉我在 super.init() 调用之前我不能引用 self 。我该如何解决这个问题,以及为什么引用 self 需要调用 super.init()? @Nathan 哦,对不起,我错过了self
参考。那么使用var
可能是一个更好的主意。或lazy var
。有问题的部分是你不能使用self
,直到整个对象被构造(在初始化之后)。而且你必须在调用super.init
之前初始化局部变量。有一些变通方法,但其中一些并不适用于所有情况。以上是关于self.init() 导致便利 init() 无限运行的主要内容,如果未能解决你的问题,请参考以下文章
为啥在我的结构中调用 self.init 之前使用了错误“self”?
CoreData 和 Codable 类编译器错误:在从初始化程序返回之前,未在所有路径上调用“self.init”
Swift: self.init (coder : aDecoder) 正在使用 EXC_BAD_ACCESS 使应用程序崩溃