我正在尝试将默认实现添加到 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 */
}
我想要完成的是所有 UIViewControllers 都将触摸转发到 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 */
}
但这不会编译,说'尾随非泛型 UIViewController 扩展的 where 子句'
我试图以另一种方式定义它,如下所示:
extension WithView where Self: UIViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
insideView.touchesBegan(touches, with: event)
}
}
虽然扩展名的格式正确,但编译器会抱怨,因为它不能“覆盖”协议扩展名中的内容。
我想要的是一个受协议约束的类扩展,例如我可以覆盖这个方法,而不是被迫在实现这个协议的所有控制器中复制粘贴代码。
编辑:根据建议的解决方案
我也想出了这个解决方案:
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 */
}
它做了我想要的,但感觉有点乱,因为所有的 UIViewControllers 都会继承这种行为,并会覆盖它的代码,检查它们是否实现了协议。