Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要self在init中设置swift类的所有常量_Swift_Self_Initializer - Fatal编程技术网

需要self在init中设置swift类的所有常量

需要self在init中设置swift类的所有常量,swift,self,initializer,Swift,Self,Initializer,我有一个Swift类,它有一个常量ivar(现在称为实例常量吗?)。要将该值设置为该常量,我需要调用所需对象的初始值设定项并传递它自己。但是,我不允许这样做,因为我需要先初始化所有值,然后调用super.init(),然后才允许访问self。那么在这种情况下该怎么办呢 class Broadcaster: NSObject, CBPeripheralManagerDelegate { let broadcastID: NSUUID let bluetoothManager: C

我有一个Swift类,它有一个常量ivar(现在称为实例常量吗?)。要将该值设置为该常量,我需要调用所需对象的初始值设定项并传递它自己。但是,我不允许这样做,因为我需要先初始化所有值,然后调用
super.init()
,然后才允许访问
self
。那么在这种情况下该怎么办呢

class Broadcaster: NSObject, CBPeripheralManagerDelegate {

    let broadcastID: NSUUID
    let bluetoothManager: CBPeripheralManager

    init(broadcastID: NSUUID) {
        self.broadcastID = broadcastID

        let options: Dictionary<NSString, AnyObject> = [ CBPeripheralManagerOptionShowPowerAlertKey: true ]
        self.bluetoothManager = CBPeripheralManager(delegate: self, queue: nil, options: options) // error: 'self' used before super.init call

        super.init()
    }
}
类广播者:NSObject、CBPeripheralManagerDelegate{
让广播ID:nsuid
让bluetoothManager:CBPeripheralManager
初始化(广播ID:NSUID){
self.broadcastID=broadcastID
let选项:Dictionary=[CBPeripheralManagerProptionShowPowerAlertKey:true]
self.bluetoothManager=cbperipheraldmanager(委托:self,队列:nil,选项:options)//在super.init调用之前使用了错误:“self”
super.init()
}
}

将您的bluetoothManager设置为一个
@lazy
属性,并在以后访问它,例如
开始转换

@lazy var bluetoothManager: CBPeripheralManager = CBPeripheralManager(delegate: self, queue: nil)

init() { ... }

func start() {

    self.bluetoothManager.startAdvertising([ "foo" : "bar" ])

}
更新Swift 1.2及更高版本 不幸的是,似乎不再可能将
bluetoothManager
作为常量。从Swift 1.2开始,在初始值设定项中,常量属性只能赋值一次。这不允许我们先将
nil
值声明为可选值,然后在初始化过程中对其进行更改。以下是以
bluetoothManager
作为变量的更新版本

class Broadcaster: NSObject, CBPeripheralManagerDelegate {

    let broadcastID: NSUUID
    var bluetoothManager: CBPeripheralManager!

    init(broadcastID: NSUUID) {
        self.broadcastID = broadcastID
        super.init()
        let options: Dictionary<String, AnyObject> = [ CBPeripheralManagerOptionShowPowerAlertKey: true ]
        self.bluetoothManager = CBPeripheralManager(delegate: self, queue: nil, options: options)
    }
}
由于
bluetoothManager
是可选的,因此在调用
super.init()
时,所有属性都会初始化(
bluetoothManager
隐式初始化为
nil
)。但是因为我们知道
bluetoothManager
在类初始化后肯定会有该值,所以我们将其声明为显式未包装,以避免在使用它时进行检查

更新

属性可以声明为常量,但仍可以在初始值设定项中更改。我们只需要确保在初始化完成时它有一个确定的值。这在Swift手册的“初始化期间修改常量属性”一章中有记录


“无主引用和隐式展开可选属性”一章中描述了需要使用调用初始化属性的情况,其中必须从尚未完全初始化的对象传递self。这是我已经尝试过的。它是有效的。但是,这就失去了出租汽车的好处/但是它需要是一个var,而不是let,不是吗?不,因为这一切都发生在初始值设定项中,它仍然可以是let。但是在类初始化之后,将无法更改它。请参阅Swift book中名为“在初始化期间修改常量属性”和“无主引用和隐式展开可选属性”的部分。老实说,在初始化super之前,需要初始化自己的实例变量,这似乎没有多大意义。super对我的实例变量一无所知。那么,背后的理由是什么?反之亦然,这对我来说更有意义。@eofster,你的答案的两部分在当前版本中都不起作用。
class Broadcaster: NSObject, CBPeripheralManagerDelegate {

    let broadcastID: NSUUID
    let bluetoothManager: CBPeripheralManager!

    init(broadcastID: NSUUID) {
        self.broadcastID = broadcastID
        super.init()
        let options: Dictionary<NSString, AnyObject> = [ CBPeripheralManagerOptionShowPowerAlertKey: true ]
        self.bluetoothManager = CBPeripheralManager(delegate: self, queue: nil, options: options)
    }
}