如何在需要自引用时在 Swift 中初始化 CBCentralManager

How to initialize CBCentralManager in Swift when a self reference is necessary

什么是初始化 CBCentralManager 实例的好方法,它需要一个委托并且通常指向拥有者 class?

我可以将 属性 声明为隐式解包的可选项,但作为一般做法这样做似乎不像 Swift 并且不太安全。

或者,我可以将 属性 声明为可选。但是由于 CBCentralManager 的初始化器没有声明为可失败的,因此声明实例似乎没有意义。

隐式展开可选:

class MyUnwrappedOptional: NSObject, CBCentralManagerDelegate {
    var centralManager: CBCentralManager! 

    func init() {
        super.init()

        centralManager = CBCentralManager(delegate: self, queue: nil, options:nil)

        // Subsequent usages of centralManager in other methods of this class don't require additional unwrapping.
        centralManager.scanForPeripheralsWithServices(services, options: nil)       
    }
}

使用可选的:

class MyOptionalClass: NSObject, CBCentralManagerDelegate {
    var centralManager: CBCentralManager?

    func init() {
        super.init()

        centralManager = CBCentralManager(delegate: self, queue: nil, options:nil)

        // Subsequent usages of centralManager in other methods of this class require optional checks:
        if let central = centralManager {
            central.scanForPeripheralsWithServices(services, options: nil)      
        }

        // :: or ::
        central!.scanForPeripheralsWithServices(services, options: nil)
    }
}

这些是更受欢迎的还是有另一种方法来实现这一点?

在初始化每个没有默认值且不是可选的非lazy 属性之前,无法在init方法中使用self(其默认值为 nil).

如果您总是在 init 中初始化 centralManager,并且您没有可能使它成为 nil 的代码,我会说 CBCentralManager! 声明是一个好的选择。这是隐式解包可选类型的主要目的之一。

以下是 the documentation about implicitly unwrapped optionals 的摘录:

Sometimes it is clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it is useful to remove the need to check and unwrap the optional’s value every time it is accessed, because it can be safely assumed to have a value all of the time.

These kinds of optionals are defined as implicitly unwrapped optionals. You write an implicitly unwrapped optional by placing an exclamation mark (String!) rather than a question mark (String?) after the type that you want to make optional.

如果程序逻辑确实允许它在某些时候可能会被使用 nil。那么普通的可选类型是合适的选择。

另一种可能的选择是您将 centralManager 属性 声明为 a lazy property。如果你这样做,它不会被创建,直到你访问它,但你将能够引用 self 并使其成为非可选的。当您需要创建它时,将决定您是否使用此选项。

lazy var centralManager: CBCentralManager = { [unowned self] () -> CBCentralManager in
    CBCentralManager.init(delegate: self, queue: nil, options: [:])
}()