Swift-在UIView的两个子类中重写一个方法

时间:2019-02-13 21:42:25

标签: ios swift uiview refactoring

我正在使用UITextFieldUIButton-MyTextFieldMyButton的自定义子类。

在这两种方法中,我都是通过以下方式创建圆角的边缘:

var round = true
override func layoutSublayers(of layer: CALayer) {
    super.layoutSublayers(of: layer)
    layer.cornerRadius = round ? self.frame.height/5.0 : 0
}

我正在尝试找到一种通用的方法来使两个类都具有round字段并覆盖layoutSublayers(...)。比在每个类中粘贴相同的代码更好的方法是什么?

3 个答案:

答案 0 :(得分:2)

或者,如果您想使用一种非常灵活的方法,则可以使用视图样式概念。这是您可以从以下开始的简单实现:

typealias Style<T> = (T) -> Void

extension UIView {

    convenience init<V: UIView>(with styles: [Style<V>]) {
        self.init(frame: .zero)
        guard let view = self as? V else {
            assertionFailure("Could not apply style for \(V.self) to \(type(of: self))")
            return
        }
        styles.forEach { $0(view) }
    }
}

然后声明一些样式表

enum ViewStyle {

    static func rounded(radius: CGFloat) -> Style<UIView> {
        return { view in
            view.layer.cornerRadius = radius
            view.clipsToBounds = true
        }
    }

    static let lightGray: Style<UIView> = { view in
        view.backgroundColor = .lightGray
    }
}

并像使用它

let button = UIButton(with: [ViewStyle.rounded(radius: 5.0)])
let textField = UITextField(with: [
    ViewStyle.rounded(radius: 8.0),
    ViewStyle.lightGray
])

它允许您重用预定义的样式并将其混合以实现更复杂的设置,而无需创建自己的自定义子类。当然,这只是可以做的一小件事,我鼓励您更进一步:)

答案 1 :(得分:1)

A。使用扩展 由于UIButtonUITextField都是UIView的子类,因此可以尝试使用方法func roundTheCorner()扩展UIView,但是必须调用roundTheCorner在自定义类的每个layoutSublayers中。仅供参考:https://docs.swift.org/swift-book/LanguageGuide/Extensions.html

B。使用运行时添加自定义属性round,然后使用swizzling方法替换layoutSublayers方法。这可能有点棘手。 仅供参考:https://nshipster.com/method-swizzling/

答案 2 :(得分:0)

也许最简单的方法是在UIButton和UITextField都继承自UIView的类上编写扩展。

extension UIView {
    func roundCorners(_ round: Bool) {
      layer.cornerRadius = round ? self.frame.height/5.0 : 0
     }
}

然后在两个子类中的某个位置调用它

roundCorners(true)