Методы расширения протокола не вызываются, когда протокол расширяет существующий протокол Apple API
Я хочу, чтобы протокол унаследовал от протокола Apple UIViewControllerTransitioningDelegate
добавьте дополнительные требования к протоколу и предоставьте реализацию по умолчанию для некоторых методов в этом протоколе. Когда я это делаю, методы не вызываются. Когда я реализую методы в самом классе, методы вызывают.
Вот о чем я говорю:
class FirstViewController: UIViewController, SlideDismissor {
let transition: PercentDrivenInteractiveTransitionWithState? = PercentDrivenInteractiveTransitionWithState()
}
protocol SlideDismissor: UIViewControllerTransitioningDelegate {
var transition: PercentDrivenInteractiveTransitionWithState? { get }
}
extension SlideDismissor {
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return nil // I do return something here, but for this example it isn't necessary
}
func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return transition
}
}
Если я добавлю следующий код, функции будут вызваны.
extension FirstViewController: UIViewControllerTransitioningDelegate {
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return nil // I do return something here, but for this example it isn't necessary
}
func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return transition
}
}
Эти методы, которые я пытаюсь предоставить для реализации по умолчанию, являются необязательными.
2 ответа
Лучшее решение для таких проблем - использовать композицию, а не наследование. Вместо того, чтобы соответствовать SlideDismissor
делегировать одному.
(Я не тестировал этот код и даже не проверял его компиляцию, но это основной подход, который я хотел бы изучить.)
class FirstViewController: UIViewController {
// Rather than handle your own transitioning, delegate it to another, reusable, object.
override func viewDidLoad() {
// Your original protocol suggested that the view controller wanted
// to control what kind of transition was used, so we pass it as a paramater.
transitioningDelegate = SlideDismissor(transition: PercentDrivenInteractiveTransitionWithState())
}
}
// In that object, implement all the delegate methods
class SlideDismissor: NSObject, UIViewControllerTransitioningDelegate {
let transition: PercentDrivenInteractiveTransitionWithState?
init(transition: PercentDrivenInteractiveTransitionWithState?) {
self.transition = transition
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return nil // I do return something here, but for this example it isn't necessary
}
func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return transition
}
}
У меня была такая же проблема, пытаясь сделать что-то подобное. По-видимому, текущим ограничением расширений протоколов является то, что мы не можем обеспечить реализации по умолчанию протоколов Objective-C. Таким образом, любой протокол, объявленный в UIKit, подпадает под эту категорию. Об этом также говорится в следующей рекомендуемой статье о протоколно-ориентированном программировании. это действительно по состоянию на сентябрь 2016 года. Я чувствую вашу боль =(но я предполагаю, что пока этот более чистый подход к расширению не реально осуществим в настоящее время