结合不同的UIView类

时间:2019-01-12 21:03:41

标签: ios swift uiview multiple-inheritance

例如,我有一个UIView的子类,例如RoundedView,ShadowedView,GradientView,并且可能想将它们组合成一个最大的类。但是,由于我们在C ++的意义上没有多重继承,并且不希望这些类具有层次结构,因此什么是最好的方法?我正在考虑协议扩展,但是由于我是Swift的新手,所以可以破坏设计。

UPD。感谢@Robert Dresler的描述性回答。这就是我的想法。但是,具体类的实现是否有任何增强,因为总会存在样板代码。

protocol Gradientable where Self: UIView {
    var startColor: UIColor { get set }
    var endColor: UIColor { get set }
    func updateColors()
}

extension Gradientable {

    var gradientLayer: CAGradientLayer {
        return layer as! CAGradientLayer
    }

    func updateColors() {
        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
    }
}

protocol CornersRoundable where Self: UIView {
    var cornerRadius: CGFloat { get set }
    func roundCorners()
}

extension CornersRoundable {
    func roundCorners() {
        self.layer.cornerRadius = cornerRadius
        self.layer.masksToBounds = true
    }
}

@IBDesignable
class SuperbView : UIView, Gradientable, CornersRoundable {

    @IBInspectable var cornerRadius: CGFloat = 6.0 {
        didSet { roundCorners() }
    }

    @IBInspectable var startColor: UIColor = .white {
        didSet { updateColors() }
    }

    @IBInspectable var endColor: UIColor = .black {
        didSet { updateColors() }
    }

    override class var layerClass: AnyClass {
        return CAGradientLayer.self
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        roundCorners()
        updateColors()
    }
}

1 个答案:

答案 0 :(得分:0)

考虑协议扩展是非常好的一点。因此,让我们看一下。


声明

让我们从简单的协议声明开始

protocol Colorable where Self: UIView {
}

我们正在使用关键字protocol,后面紧跟协议名称。然后,如果需要,我们可以将协议限制为特定的类型,即where Self: Type。假设我们将其限制为UIView。现在我们的协议可以用于类型UIView(以及所有继承的类)上。

现在让我们声明一些变量

protocol Colorable where Self: UIView {
    var mainColor: UIColor { get set }
}

...我们要声明,每个符合协议Colorable的视图都必须声明变量mainColor


实施

现在,如何实施我们的协议? Swift中的约定是在扩展中声明协议,但是您也可以在声明类型

之后立即声明它
extension MyView: Colorable {}

class MyView: UIView, Colorable {}

清除?现在,我们必须从协议声明中添加所有必需的内容。因为我们只声明了一个变量,所以我们放它,然后给它赋一个值

class MyView: UIView {
    var mainColor: UIColor = .black
}

添加功能

一切还清楚吗?好的,让我们继续向协议添加一些方法

protocol Colorable where Self: UIView {
    var mainColor: UIColor { get set }
    func doSomethingWithColor()
}

现在我们必须在我们的视图子类中声明此方法,或者我们可以在协议扩展中声明此方法。既然我们知道,该协议还需要声明变量mainColor,我们就可以使用它

extension Colorable {
    func doSomethingWithColor() {
        backgroundColor = mainColor
    }
}

然后我们可以在符合该协议的任何视图上调用它

let myView = MyView()
myView.doSomethingWithColor()

具有一般约束的方法

现在是最后一部分。假设我们有UIViewController,其中包括三个不同类型的视图,并且都符合协议Colorable。这使我们可以对方法使用一般约束。这个约束声明了类型,比方说T,它符合协议。我们可以将这种类型用作方法的参数,并且我们将100%确信正在传递的视图正是我们所需要的,在我们的例子中,变量mainColor

func changeBorderColorOf<T: Colorable>(_ view: T) {
    view.layer.borderColor = view.mainColor.cgColor
}

现在我们可以调用此方法,并且可以通过任何符合我们协议的UIView作为参数

let myView = MyView()
changeBorderColorOf(myView)

泛型是一个大话题,所以我希望这会帮助您入门! ;-)