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

有沒有辦法利用的協議擴展初始化,這樣它就會在框架現有的初始化過程中自動調用?

回答

0

你不需要需要來調用不同的初始化程序;你已經初始化了。此外,您不需要將self轉換爲MyProtocol;你已經聲明它採用MyProtocol。另外,您已經將MyProtocol的setupLocationManager注入FirstViewController,因爲您的FirstViewController已經採用MyProtocol,並且MyProtocol上的擴展名針對的是FirstViewController的超類UIViewController。

所以,該方法已經注入;現在就開始吧,在你已經運行的初始化器中調用注入的方法。您的代碼的以下縮減版本編譯得非常好:

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