【问题标题】:How to declare variable that extends specific superclass and conforms to a protocol如何声明扩展特定超类并符合协议的变量
【发布时间】:2015-01-15 11:30:03
【问题描述】:

我想声明一个符合特定协议的视图。一方面,我需要能够将其指定为 UIView,以便能够将其添加为子视图并期望符合协议。

问题开始于,我想为一个可以编辑或不可编辑的文本视图创建一个通用容器。

我决定为此使用不同的类——当它不可编辑时为 UILabel,当它可编辑时为 UITextField。所以在我的通用容器中,我希望能够 1. 将视图添加为子视图 2. 能够设置文本。

UILabel 和 UITextField 没有设置文本的通用接口,所以我让它们使用扩展实现一个新协议:

protocol TextView {
    var text_:String? {get set}
}

extension UILabel:TextView {

    var text_:String? {
        get {
            return self.text
        }
        set {
            self.text = newValue
        }
    }
}


extension UITextField: TextView {

    var text_:String? {
        get {
            return self.text
        }
        set {
            self.text = newValue
        }
    }
}

到目前为止一切顺利 - 但在我的容器视图中,我需要将通用视图声明为 UIView TextView。如果我将其作为 TextView 进行,则必须进行转换才能将它们添加为子视图,如果将其声明为 UIView,则必须在要设置文本时进行转换。

我希望能够指定(编译时间)“此变量是符合 TextView 协议的 UIView”之类的内容。我怎样才能做到这一点?如果不可能,解决此类问题的推荐方法是什么?

谢谢!

【问题讨论】:

  • 您要检查UIView 实例变量是否符合您的协议?
  • @rakeshbs 不完全是,我知道我可以在运行时使用 is/as 进行此类检查。我希望能够设置一个约束或其他东西,以便编译器强制该变量是一个也符合 TextView 协议的 UIView。但我怀疑这是不可能的。在那种情况下,我想知道一个可用的设计模式/不同的方法来解决这个问题。
  • 哦,该死的!实际上,该线程中的问题回答了我的问题 - 不确定这是否是有效的重复。我知道我错过了一些基本的东西:<T where T:UIView, T:TextView>
  • 那我认为这不是一个重复的问题。 可能之前已经回答过,但可能很难找到确切的重复项。

标签: swift


【解决方案1】:

感谢 Martin R 的评论,我找到了答案,这比我想象的要简单得多。在我的容器类中,我必须声明类型约束:

class MyContainer<T where T:UIView, T:TextView> {...}

使用要重写的方法:

func createValueTextView() -> T {fatalError("must override!")}

然后我可以将我的 T 实例用作 UIView TextView,这正是我所需要的!

然后是具有可编辑字段的容器的子类:

class MyEditableContainer<A>: MyContainer<UITextField> {...}

我重写 createValueTextView 以返回 UITextField:

func createValueTextView() -> UITextField {return UITextField()}

同样是不可编辑的:

class MyEditableContainer<A>: MyContainer<UILabel> {...} 
func createValueTextView() -> UILabel {return UILabel()}

(请注意,类型参数 'A' 是 Swift 当前需要的“丢弃”参数,请参阅this thread 了解更多信息)。

此外,在 TextHolder 或类似的名称中重命名 TextView 可能会很好,因为协议本身与视图无关。正如我在 cmets 中提到的那样,尽管在此线程中将其设置为“TextView”,但它们不再可编辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多