更簡潔的 UIKit Setter

· 2min
Table of Contents

前言

透過 Swift 的 Extension 來讓 UIKit 設置更整潔.

實作

利用 Swift Extensions + KeyPath 達到實作.

extension NSObjectProtocol {
    @discardableResult
    func setup<Value>(_ keypath: ReferenceWritableKeyPath<Self, Value>, value: Value) -> Self {
        self[keyPath: keypath] = value

        return self
    }

    @discardableResult
    func setup<Value>(_ keypath: ReferenceWritableKeyPath<Self, Value>, condition: () -> Value) -> Self {
        self[keyPath: keypath] = condition()

        return self
    }
}

使用

使用前:

let mainView: UIView = .init(frame: .zero)
mainView.backgroundColor = .green
mainView.frame = .init(x: 0, y: 0, width: 200, height: 200)

let subView: UIView = .init(frame: .zero)
subView.translatesAutoresizingMaskIntoConstraints = false
subView.backgroundColor = .red
subView.clipsToBounds = true
subView.layer.cornerRadius = 10

mainView.addSubview(subView)

使用後:

let mainView: UIView = .init(frame: .zero)
    .setup(\.backgroundColor, value: .green)
    .setup(\.frame, value: .init(x: 0, y: 0, width: 200, height: 200))

let subView: UIView = .init(frame: .zero)
    .setup(\.translatesAutoresizingMaskIntoConstraints, value: false)
    .setup(\.backgroundColor, value: .red)
    .setup(\.clipsToBounds, value: true)
    .setup(\.layer.cornerRadius, value: 10)

mainView.addSubview(subView)

看起來是不是整潔多了.

甚至可以使用條件設置, ex:

let subView: UIView = .init(frame: .zero)
    .setup(\.translatesAutoresizingMaskIntoConstraints, value: false)
    .setup(\.clipsToBounds, value: true)
    .setup(\.layer.cornerRadius, value: 10)
    .setup(\.backgroundColor) { // 使用條件式
        Bool.random() ? .black : .white
    }

由於是 NSObjectProtocol Extension, 基本上繼承 NSObject 的 Class 都能使用, ex:

let vc: UIViewController = .init()
    .setup(\.title, value: "HelloWorld")
    .setup(\.modalPresentationStyle, value: .overFullScreen)