在swift中约束到协议的类扩展中重写方法

在swift中约束到协议的类扩展中重写方法,swift,uiviewcontroller,protocols,protocol-extension,Swift,Uiviewcontroller,Protocols,Protocol Extension,我试图通过协议扩展将默认实现添加到所有符合协议的控制器的UIViewController中。在那里,触摸将被发送到一个自定义视图,所有实现此协议的控制器都具有该视图 以下是初始状态: protocol WithView { var insideView: UIView! { get } } class Controller1: UIViewController, WithView { var insideView: UIView! override func tou

我试图通过协议扩展将默认实现添加到所有符合协议的控制器的UIViewController中。在那里,触摸将被发送到一个自定义视图,所有实现此协议的控制器都具有该视图

以下是初始状态:

protocol WithView {
    var insideView: UIView! { get }
}

class Controller1: UIViewController, WithView {

    var insideView: UIView!

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        insideView.touchesBegan(touches, with: event)
    }

    /* Functionality of Controller 1 */
}

class Controller2: UIViewController, WithView {

    var insideView: UIView!

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        insideView.touchesBegan(touches, with: event)
    }

    /* Functionality of Controller 2 */
}
protocolwithview{
var insideView:UIView!{get}
}
类控制器1:UIViewController,WithView{
var insideView:UIView!
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
insideView.TouchesBegined(触摸,带有:事件)
}
/*控制器1的功能*/
}
类控制器2:UIViewController,WithView{
var insideView:UIView!
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
insideView.TouchesBegined(触摸,带有:事件)
}
/*控制器2的功能*/
}
我想实现的是这样一种情况:所有UIViewController都将触摸转发到insideView,而没有以相同的方式为每个控制器指定触摸。大概是这样的:

protocol WithView {
    var insideView: UIView! { get }
}

extension UIViewController where Self: WithView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        insideView.touchesBegan(touches, with: event)
    }
}

class Controller1: UIViewController, WithView {

    var insideView: UIView!

    /* Functionality of Controller 1 */
}

class Controller2: UIViewController, WithView {

    var insideView: UIView!

    /* Functionality of Controller 2 */
}
protocolwithview{
var insideView:UIView!{get}
}
扩展UIViewController,其中Self:WithView{
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
insideView.TouchesBegined(触摸,带有:事件)
}
}
类控制器1:UIViewController,WithView{
var insideView:UIView!
/*控制器1的功能*/
}
类控制器2:UIViewController,WithView{
var insideView:UIView!
/*控制器2的功能*/
}
但这不会编译,说“非泛型类型UIViewController的扩展的尾部where子句”

我试着用另一种方式来定义它,就像这样:

extension WithView where Self: UIViewController {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        insideView.touchesBegan(touches, with: event)
    }
}
扩展WithView,其中Self:UIViewController{
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
insideView.TouchesBegined(触摸,带有:事件)
}
}
当扩展正确格式化时,编译器会抱怨,因为它无法“覆盖”协议扩展中的内容

我想要的是一个受限于协议的类扩展,比如我可以重写这个方法,而不必在实现这个协议的所有控制器中复制粘贴代码

编辑:根据建议的解决方案

我还提出了这个解决方案:

protocol WithView {
    var insideView: UIView! { get }
}

extension UIViewController {
    override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let viewSelf = (self as? WithView) else {
            super.touchesBegan(touches, with: event)
            return
        }
        viewSelf.insideView.touchesBegan(touches, with: event)
    }
}

class Controller1: UIViewController, WithView {

    var insideView: UIView!

    /* Functionality of Controller 1 */
}

class Controller2: UIViewController, WithView {

    var insideView: UIView!

    /* Functionality of Controller 2 */
}
protocolwithview{
var insideView:UIView!{get}
}
扩展UIViewController{
覆盖open func ToucheSBegind(Touchs:Set,带有事件:UIEvent?){
guard let viewSelf=(自身为?WithView)else{
super.touchesbeated(touches,with:event)
返回
}
viewSelf.insideView.touchesbeated(touches,with:event)
}
}
类控制器1:UIViewController,WithView{
var insideView:UIView!
/*控制器1的功能*/
}
类控制器2:UIViewController,WithView{
var insideView:UIView!
/*控制器2的功能*/
}

它符合我的要求,但感觉有点混乱,因为所有UIViewController都会执行此行为,并覆盖其代码,检查它们是否实现了协议。

您可以通过创建一个类并从中进行子分类来完成此操作:

class WithViewController: UIViewController, WithView {

    var insideView: UIView!

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        insideView.touchesBegan(touches, with: event)
    }
}

class ViewController: WithViewController {

}
class WithViewController:UIViewController,WithView{
var insideView:UIView!
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
insideView.TouchesBegined(触摸,带有:事件)
}
}
类ViewController:WithViewController{
}

唯一的缺点是您必须有一个默认的
insideView
,并且它永远不会被更改。

您可以为所有视图控制器定义自己的超类,并检查
self
是否符合特定的协议(
WithView
,在您的情况下),以决定是否应该将触摸事件转发到任何其他视图

class MyViewController: UIViewController {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let selfWithView = self as? WithView {
            selfWithView.insideView.touchesBegan(touches, with: event)
        } else {
            super.touchesBegan(touches, with: event)
        }
    }
}
类MyViewController:UIViewController{
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
如果让selfWithView=selfas?WithView{
selfWithView.insideView.touchesbeated(touches,with:event)
}否则{
super.touchesbeated(touches,with:event)
}
}
}

这是一种更灵活的方法,您不必在每个视图控制器子类中存储
insideView
属性。

这是可行的,但这里的要点是更改子类模式(在我的示例中,Controller1用于继承“WithViewController”,将此视图封装在UIViewController中)。我想避免这种情况,因为它违背了我的目的,因为我会复制相同的模式我想出了一个稍微好一点的方法,所以我会在UIViewController上有一个扩展,覆盖touchsbegind,这会像你说的那样。但它仍然感觉混乱,虽然。。。我认为应该有一个更好的“快速”解决方案this@JordiSerra同意。老实说,几个月前我才从Obj-C转到Swift,所以我也在探索它的好处。使用扩展而不是子类化的好方法!我刚刚了解到我的方法是错误的,LOL.[此处][声明“扩展无法覆盖现有功能”。因此,尽管编译器编译和运行良好,但这是不允许的,原则上它可能导致不希望的行为。啊,这是有道理的