【问题标题】:Subclass/Extend UIView so all other Views (UIImageView, UITextField ...) inherit upon creation子类/扩展 UIView 以便所有其他视图(UIImageView、UITextField ...)在创建时继承
【发布时间】:2017-06-26 00:01:18
【问题描述】:

当我想向 UIView 添加功能以便我的应用程序中的所有视图都获得这些功能时,建议的方法是什么?事实上,我也需要添加一些存储的属性,所以扩展是不可能的。由于我需要处理 Textfields、ImageViews、Views(以及谁知道还会发生什么),我不想为每个子类添加该功能,所以目标是创建 UIView 的子类和我的所有控件(如果可能的话)开箱即用地获取该功能。

使用扩展会很容易,但正如我所说,我也需要存储一些东西,那么这个目标可以通过子类实现吗?或者什么是正确的方法(也许还有第三种选择)

谢谢

【问题讨论】:

  • 嘿,我在 2-3 年前看到了一个类似的问题,并且得到了回答 -> 请更好地查看 SO.. 我认为关键是使用这个 developer.apple.com/documentation/objectivec/… 方法......但是你应该小心这一点,因为例如“UITextField”超级是“UIControl”——它似乎也被弃用了
  • 是的,像这样的 smt 将是完美的,但显然扼杀了这个选项。我会搜索是否有类似的smt for swift
  • 在运行时使用objective-c中的关联属性有一种令人讨厌的方法,但是很糟糕。最好谈谈为什么您认为需要向这些视图添加属性并考虑一些替代方案。作为一般原则,一堆视图用于呈现和编辑模型,通常是我们尝试通过属性丰富的模型。
  • 主要是关于转型。我希望我的所有视图在特殊环境中(意味着当父级特殊时)具有所有转换功能(拖动、旋转、缩放......)。而且我认为在 UIView 中这样做会很好,而不是特别针对每个 View(bcz 代码实际上与 UIImageView、UITextView 有 90% 相似)。因此我还需要存储一些转换信息。但似乎我必须为我想要支持的每种视图类型都这样做......

标签: ios iphone uiview subclass extension-methods


【解决方案1】:

为什么不在协议扩展中定义协议并提供默认实现,然后让 UIView 符合该协议?这是一个例子:

protocol MyProto {
    var someVar: Bool { get set }
    func someFunc() -> Void
}

extension MyProto {
    var someVar: Bool {
        get {
            // provide default implementation
            return true
        }
        set {

        }
    }

    func someFunc() -> Void {
        // provide common implementation
    }
}

extension UIView: MyProto {}

您还可以使用where 子句来约束类型的默认行为。

extension MyProto where Self: UIControl {
    var someVar: Bool {
        get {
            return isUserInteractionEnabled
        }
        set {
            isUserInteractionEnabled = newValue
        }
    }
}

extension MyProto where Self: UITextField {
    var someVar: Bool {
        get {
            return isFirstResponder
        }
        set {
            newValue ? becomeFirstResponder() : resignFirstResponder()
        }
    }
}

【讨论】:

  • Bcz 这部分在扩展“var someVar: Bool”中无效
  • 怎么无效?
  • 但我仍然需要在“someVar”中存储一些值。我也需要一个二传手,然后你得到错误
  • 只需在协议定义中设置属性 Settable 即可。我刚刚更新了我的答案以适合您的用例。
  • 也许我没有看到它,但我仍然不明白(尽管我真的很惊讶你可以用 swift 协议做什么)。但要指出的是,我有一个属性来存储视图的最后位置(所以最后一次拖动视图),我将在哪里/以及如何在您的设置中存储该值?
【解决方案2】:

TLDR;您不能这样做,并且您需要将每个要引入新属性的 UI 元素子类化。

您不能这样做(无法访问源代码),因为您将通过在 UIView 及其子类之间注入您自己的类来有效地更改类继承树。

考虑如果一种语言允许这样做的含义:

  • Class A 定义一个属性,a
  • Class Binherits 来自Class A 并定义了一个属性b,这很好,因为Class A 没有这个属性。
  • Class C 继承自 Class B 并具有 ab 属性。

现在,如果你可以“注入”Class A1 以某种方式“低于”Class A,会发生什么?

  • Class A1 可以定义一个属性b,这很好,因为Class A 没有这个属性
  • Class B 现在有一个问题,因为 its b 与超类 b 发生冲突
  • Class C 具有属性 b 的多重继承钻石问题

当然,您只打算添加不冲突的属性(尽管您不知道这一点,因为您不知道所有可能的子类实现)并且不需要子类来访问您的属性,所以多重继承 不是问题,但如果这样的功能是一种语言,则需要解决这些潜在问题,因为您不能依赖与您有相同意图的每个人。

【讨论】:

  • 我其实想更深入地了解这一点,也写了一些东西,但由于不可能,我决定删除它,因为讨论它会浪费时间:) 谢谢你的回答和澄清
猜你喜欢
  • 2019-07-15
  • 1970-01-01
  • 2014-07-10
  • 2018-08-08
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多