Как вызвать инициализаторы расширений протокола в назначенных инициализаторах?

Я пытаюсь внедрить инициализатор расширения протокола в назначенный инициализатор существующего класса. Я не думаю, что есть способ обойти это без переопределения назначенного инициализатора из класса, а затем вызвать инициализатор расширения протокола внутри.

Ниже показано, что я пытаюсь сделать, особенно с классом UIViewController:

class FirstViewController: UIViewController, MyProtocol {

    var locationManager: CLLocationManager?
    var lastRendered: NSDate?

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        // TODO: How to call MyProtocol initializer?
        // (self as MyProtocol).init(aDecoder) // Didn't compile
    }

}

protocol MyProtocol: CLLocationManagerDelegate {

    var locationManager: CLLocationManager? { get set }
    var lastRendered: NSDate? { get set }

    init?(coder aDecoder: NSCoder)
}

extension MyProtocol where Self: UIViewController {

    // Possible to inject this into initialization process?
    init?(coder aDecoder: NSCoder) {
        self.init(coder: aDecoder)
        setupLocationManager()
    }

    func setupLocationManager() {
        locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.desiredAccuracy = kCLLocationAccuracyThreeKilometers
        locationManager?.distanceFilter = 1000.0
        locationManager?.startUpdatingLocation()
    }

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // TODO
    }

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        // TODO
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        // TODO
    }
}

Есть ли способ использовать инициализаторы расширений протокола, чтобы он вызывался автоматически во время существующего процесса инициализации фреймворка?


person TruMan1    schedule 21.02.2016    source источник


Ответы (1)


Вам не нужно вызывать другой инициализатор; вы уже инициализируете. Более того, вам не нужно приводить self к MyProtocol; вы уже заявили, что он принимает MyProtocol. Кроме того, вы уже внедрили setupLocationManager MyProtocol в FirstViewController, потому что ваш FirstViewController уже принимает MyProtocol, а расширение MyProtocol нацелено на UIViewController, надкласс FirstViewController.

Итак, метод уже внедрен; теперь просто продолжайте и вызовите введенный метод прямо в инициализаторе, который вы уже используете. Следующая урезанная версия вашего кода прекрасно компилируется:

class FirstViewController: UIViewController, MyProtocol {
    var locationManager: CLLocationManager?

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.setupLocationManager() // no problem!
    }
}

protocol MyProtocol: CLLocationManagerDelegate {
    // this next line is necessary so that
    // ...setupLocationManager can refer to `self.locationManager`
    var locationManager: CLLocationManager? { get set }
}

extension MyProtocol where Self: UIViewController {
    func setupLocationManager() {
        locationManager = CLLocationManager()
        // ... etc.
    }
    // ... etc.
}
person matt    schedule 21.02.2016