如何为子类覆盖快速协议功能(例如,UIView中的UILabel)

Poi*_*ter 8 protocols uiview ios swift

我正在尝试实现一个扩展功能,该功能应根据使用它的类的类型而有所不同。这些对象必须是UIView(或子类)。它应该始终使用在指定类型上扩展的函数,但如果不符合任何扩展函数,则应改用UIView方法(作为后备)。

这是我要执行的操作的一个示例:

protocol aProtocol {
    typealias completionBlock = (_ finished:Bool)->()
    func doSomething(completion: completionBlock)
}


extension UIView: aProtocol {
    func doSomething(completion: (Bool) -> ()) {
        print("Im an UIView")
    }
}

extension aProtocol where Self: UILabel {
    func doSomething(completion: (Bool) -> ()) {
        print("im an UILabel")
    }
}

extension aProtocol where Self: UIImageView {
    func doSomething(completion: (Bool) -> ()) {
        print("im an UIImageView")
    }
}
Run Code Online (Sandbox Code Playgroud)

执行:

UIView().doSomething { (foo) in } // Should print "Im an UIView"
UIButton().doSomething { (foo) in } // Should print "Im an UIView" (UIButton doesent have specified extended function so should fall back on the UIView function)
UILabel().doSomething { (foo) in } // Should print "im an UILabel"
UIImageView().doSomething { (foo) in } // Should print "im an UIImageView"
Run Code Online (Sandbox Code Playgroud)

现在打印:

Im an UIView
Im an UIView
Im an UIView
Im an UIView
Run Code Online (Sandbox Code Playgroud)

这意味着它始终使用UIView方法,即使我希望它使用自己的方法也是如此。我的目标是这样打印:

Im an UIView
Im an UIView
im an UILabel
im an UIImageView
Run Code Online (Sandbox Code Playgroud)

Kam*_*ran 5

您可以通过以下方式实现,您只需在中将其方法公开aProtocolObjective-c运行时即可。overridingextension

@objc protocol aProtocol {
    typealias completionBlock = (_ finished:Bool)->()
    func doSomething(completion: completionBlock)
}

extension UIView: aProtocol {
    func doSomething(completion: (Bool) -> ()) {
        print("Im an UIView")
    }
}

extension UILabel {
    override func doSomething(completion: (Bool) -> ()) {
        // you can call super.doSomething(completion: completion)
        print("im an UILabel")
    }
}

extension UIImageView {
    override func doSomething(completion: (Bool) -> ()) {
        // you can call super.doSomething(completion: completion)
        print("im an UIImageView")
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Im an UIView
Im an UIView
im an UILabel
im an UIImageView
Run Code Online (Sandbox Code Playgroud)

  • @Vollan [此处](/sf/answers/3875616181/)是解释。 (2认同)