web-dev-qa-db-ja.com

Swift initのクラスのすべての定数を設定するために自己が必要

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()
    }
}
29
Michael Ochs

Swift 1.2以降の更新

残念ながら、bluetoothManagerを定数として使用することはできなくなったようです。 Swift 1.2から始まり、イニシャライザでは、定数プロパティは値を1回しか割り当てることができません。これにより、オプションとして宣言して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()の後に値を割り当てることができます。

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

bluetoothManagerはオプションであるため、super.init()が呼び出されるまでに、すべてのプロパティが初期化されます(bluetoothManagernilで暗黙的に初期化されます)。ただし、クラスが初期化された後はbluetoothManagerが確実に値を持つことがわかっているため、使用時のチェックを回避するために、明示的にアンラップされたものとして宣言します。

更新

プロパティは定数として宣言でき、初期化子で変更できます。初期化が完了するまでに、値が明確であることを確認する必要があります。これは、Swiftブックの「初期化中の定数プロパティの変更」の章に記載されています。

まだ完全に初期化されていないオブジェクトからselfを渡す必要がある呼び出しでプロパティを初期化する必要がある状況については、「所有されていない参照と暗黙的にアンラップされたオプションプロパティ」の章で説明します。

34
eofster

BluetoothManagerを@lazyプロパティを使用して、後でアクセスします。 startAdvertising

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

init() { ... }

func start() {

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

}
1
Karl