Swift - 覆盖 UIView 的两个子类中的方法



我正在使用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(...).有什么比在每个类中粘贴相同的代码更好的方法呢?

或者,如果你想有一个真正灵活的方式,你可以使用视图样式概念。以下是您可以从以下简单实现开始的:

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
])

它将允许您重用预定义的样式并混合它们以实现更复杂的设置,而无需创建自己的自定义子类。当然,这只是可以做什么的一个小预告片,我鼓励你更深入:)

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

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

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

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

然后在两个子类中的某个地方调用它,例如

roundCorners(true)

最新更新