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