在swift中约束到协议的类扩展中重写方法
我试图通过协议扩展将默认实现添加到所有符合协议的控制器的UIViewController中。在那里,触摸将被发送到一个自定义视图,所有实现此协议的控制器都具有该视图 以下是初始状态:在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
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.[此处][声明“扩展无法覆盖现有功能”。因此,尽管编译器编译和运行良好,但这是不允许的,原则上它可能导致不希望的行为。啊,这是有道理的