1

既存のクラスの指定された初期化子にプロトコル拡張初期化子を挿入しようとしています。クラスから指定された初期化子をオーバーライドせずにそれを回避する方法はないと思います。次に、プロトコル拡張初期化子を呼び出します。

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

フレームワークの既存の初期化プロセス中に自動的に呼び出されるように、プロトコル拡張初期化子を利用する方法はありますか?

4

1 に答える 1

1

別のイニシャライザを呼び出す必要はありません。あなたはすでに初期化しています。selfさらに、 MyProtocolにキャストする必要はありません。MyProtocolを採用することをすでに宣言しています。さらに、setupLocationManagerFirstViewController は既に MyProtocol を採用しており、MyProtocol の拡張機能は FirstViewController のスーパークラスである UIViewController を対象としているため、MyProtocol は 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.
}
于 2016-02-21T20:01:49.637 に答える