两个 类 使用相同的函数创建自定义视图 - Swift

Two classes to use the same function to create custom view - Swift

我是 Swift 的新手,我搞不懂。我有两个 classes,我需要使用相同的函数来设置自定义 UIStackVIew(显示评级星级的评级控件)。每个 class 都有一个名为 value 的变量需要在函数内部传递。我不想在每个 class 中复制 setUpStackView 函数的相同代码。我有以下代码:

class Class1: UIStackView {

    var variable1 = "value1"

    override init(frame: CGRect){
      super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder){
      super.init(coder: aDecoder)
    }

    setUpStackView(value: variable1)

}

class Class2: UIStackView {

    var variable2 = "value2"

    override init(frame: CGRect){
      super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder){
      super.init(coder: aDecoder)
    }

    setUpStackView(value: variable2)

}




extension Class1 {

  func setUpStackView(value: String){
    //code to set UIStackView rating control and to use the variable value
  }

}

如何实现 Class2 的扩展?我坚持这个。任何帮助将不胜感激!

你有很多选择。

您可以让 Class2 继承自 Class1:

class Class2: Class1 {
    var value = "value2" //You have access to Class1's value, so you can change it here
    setUpStackView(value: value) //But there's a problem here
}

但是您不能在 class 声明的中间调用函数。 但是你可以在初始化器中这样做:

class Class2: Class1 {

    override init(frame: CGRect) {
        super.init(frame: frame)
        value = "value2" 
        setUpStackView(value: value) 
    }

    required init(coder aDecoder: NSCoder){
        super.init(coder: aDecoder)
        value = "value2"
        setUpStackView(value: value) 
    }
}

上面的代码有点乱,因为您在它自己的初始化程序中引用了 class 属性。 这是另一个解决方案:

您可以使您的设置功能成为 UIStackView 的功能扩展:

extension UIStackView {
    func setUpStackView(value: String) { 
        //Your setup here
        self.someProperty = value //self is referring to the stackview itself
    }
}

另一种选择是创建静态函数。

extension Class1 {
    static func setUpStackView(stackVw: UIStackView, value: String) {
        stackVw.someProperty = value 
        //Doing it like this still makes this function "belong" to Class1
        //It also makes it so anyone can set up their stack view like
        //this because they have to pass their stack view in here
    }
}

不管你在什么 class 以及你有什么继承层次,用法都是这样的:

override init(frame: CGRect) {
    super.init(frame: frame)
    Class1.setUpStackVw(stackVw: self, value: self.variable)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    Class1.setUpStackVw(stackVw: self, value: self.variable)
}

另一种选择是创建一个 Class1 和 Class2 都遵守的协议。

protocol StackVwWithSpecialSetUp where Self: UIStackView {
    var value: String {get}
}
extension StackVwWithSpecialSetUp {
    func setUpStackView() 
    {
        self.someProperty = self.value
    }
}

然后您的 class 将符合它

class Class1Or2: UIStackView, StackVwWithSpecialSetUp {
    var value: String = "blah" //Compiler will force you to implement this
    override init(frame: CGRect) {
        super.init(frame: frame)

        //Now you can use this
        setUpStackVw()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        //You can use this here too
        setUpStackVw()
    }
}

也许我的做法是完全消除对 value 属性 的需求:

class Class1: UIStackView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUpStackVw()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setUpStackVw()
    }

    func setUpStackVw()
    {
        self.accessibilityHint = "value1"
    }
}

//////////

class Class2: Class1 {
    override func setUpStackVw()
    {
        self.someProperty = "value2"
    }
}

一个解决方案可以将通用代码移动到可以抽象出来的协议中:

protocol  BaseStackView {
    var variable :String { get set }
}

class Class1: UIStackView,BaseStackView {



    var variable = "value1"

    override init(frame: CGRect){
      super.init(frame: frame)
        self.setUpStackView(value: variable)

    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
        self.setUpStackView(value: variable)
    }
}

class Class2: UIStackView,BaseStackView {

    var variable = "value2"

    override init(frame: CGRect){
      super.init(frame: frame)
        self.setUpStackView(value: variable)
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
        self.setUpStackView(value: variable)
    }



}



extension UIStackView {
    func setUpStackView(value: String) {
        //Your setup here
    }
}