Подтвердить что ты не робот

Нужно, чтобы я установил все константы быстрого класса в 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()
    }
}
4b9b3361

Ответ 1

UPDATE для Swift 1.2 и более поздних версий

К сожалению, похоже, что он не может быть bluetoothManager как константа. Начиная с Swift 1.2, в инициализаторе постоянные свойства могут присваивать значение только один раз. Это не позволяет нам начать с значения nil, объявив его как необязательный и изменив его позже в процессе инициализации. Heres обновленная версия с 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() все свойства инициализируются (bluetoothManager неявно инициализируется с помощью nil). Но поскольку мы знаем, что bluetoothManager будет определенно иметь значение после инициализации класса, мы объявляем его как явно развернутое, чтобы избежать проверок при его использовании.

ОБНОВЛЕНИЕ

Свойство может быть объявлено как постоянное и все еще изменено в инициализаторе. Нужно просто убедиться, что он имеет определенное значение к завершению инициализации времени. Это описано в главе "Изменение константных свойств во время инициализации" книги Swift.

Ситуация, когда свойство должно быть инициализировано вызовом, в котором self должен быть передан из еще не полностью инициализированного объекта, описан в главе "Неопубликованные ссылки и неявно разворачиваемые дополнительные свойства".

Ответ 2

Как настроить свой bluetoothManager как свойство @lazy и получить доступ к нему позже, например. до startAdvertising?

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

init() { ... }

func start() {

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

}