Методы расширения протокола не вызываются, когда протокол расширяет существующий протокол 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 года. Я чувствую вашу боль =(но я предполагаю, что пока этот более чистый подход к расширению не реально осуществим в настоящее время

Другие вопросы по тегам