2

I want a protocol to inherit from an Apple protocol UIViewControllerTransitioningDelegate, add additional protocol requirements and provide a default implementation for some methods in that protocol. When I do that, the methods do not get called. When I implement the methods in the class itself, the methods do get called.

Here's what I'm talking about:

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

If I add the following code the functions do get called.

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
    }

}

These methods I'm trying to provide a default implementation for are optional methods.

4

2 回答 2

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
    }
}
于 2016-09-27T15:52:44.800 回答
1

我在尝试做类似的事情时遇到了同样的问题。显然,协议扩展的当前限制似乎是我们无法提供 Objective-C 协议的默认实现。因此,在 UIKit 中声明的任何协议都属于这一类。这也说明了以下有关面向协议编程的推荐文章。这自 2016 年 9 月起有效。我感到你的痛苦 =( 但我想目前这种更清洁的扩展方法暂时并不可行

于 2016-09-27T15:24:09.287 回答