问题
What are good ways to initialize an instance of CBCentralManager, which requires a delegate and is often pointing to the owning class?
I could declare the property as an implicitly unwrapped optional but doing so as a general practice seems rather not Swift-like and not very safe.
Alternatively, I can declare the property as an optional. But since CBCentralManager's initializers are not declared as failable, it doesn't seem to make sense to declare the instance as such.
Implicitly Unwrapped Optional:
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)
}
}
Using An Optional:
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)
}
}
Is either of these more preferred or is there another way to achieve this?
回答1:
There is no way to use self
in an init
method prior to initializing every non-lazy
property that has no default value and is not optional (which have a default value of nil
).
If you always initialize centralManager
in init
, and you have no code that will potentially make it nil
, I would say that the CBCentralManager!
declaration is a good choice. That is one of the main purposes of the implicitly unwrapped optional type.
Here is the excerpt from 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.
If the program logic does potentially allow for it to be nil
at some point when it might be used. Then a normal optional type is the appropriate choice.
One other possible option would be for you to declare your centralManager
property as a lazy property. If you do this it won't be created until you access it, but you will be able to reference self
and make it non-optional. When you need it to be created will govern if you use this option or not.
lazy var centralManager: CBCentralManager = { [unowned self] () -> CBCentralManager in
CBCentralManager.init(delegate: self, queue: nil, options: [:])
}()
来源:https://stackoverflow.com/questions/33189011/how-to-initialize-cbcentralmanager-in-swift-when-a-self-reference-is-necessary