Skip to content

Instantly share code, notes, and snippets.

@yoching
Last active June 5, 2020 04:28
Show Gist options
  • Save yoching/40d329f5a314d379edf9a8ddf414e15d to your computer and use it in GitHub Desktop.
Save yoching/40d329f5a314d379edf9a8ddf414e15d to your computer and use it in GitHub Desktop.
Functional View Styling using `callAsFunction`
import UIKit
struct Style<View: UIView> {
let apply: (View) -> View
// from swift 5.2
func callAsFunction(_ view: View) -> View {
apply(view)
}
}
extension Style {
// general style composition (functional composition)
func with(_ another: Style<View>) -> Style<View> {
return .init { view -> View in
another(self(view))
}
}
}
// styles for UIView (generic)
extension Style {
static func cornerRadius(_ radius: CGFloat) -> Self {
.init { view -> View in
view.layer.cornerRadius = radius
return view
}
}
static func backgroundColor(_ color: UIColor) -> Self {
.init { view -> View in
view.backgroundColor = color
return view
}
}
}
// styles only for UILabel
extension Style where View == UILabel {
static func font(_ font: UIFont) -> Self {
.init { label -> UILabel in
label.font = font
return label
}
}
}
// styles only for UIButton
extension Style where View == UIButton {
static func titleColor(_ color: UIColor, for state: UIControl.State) -> Self {
.init { button -> UIButton in
button.setTitleColor(color, for: state)
return button
}
}
}
// composed style
let labelStyle: Style<UILabel> = Style.cornerRadius(5)
.with(.backgroundColor(.white))
.with(.font(UIFont.systemFont(ofSize: 15)))
let buttonStyle: Style<UIButton> = Style.cornerRadius(10)
.with(.backgroundColor(.black))
.with(.titleColor(.white, for: .normal))
// apply style to view
let label = UILabel()
labelStyle(label)
let button = UIButton()
buttonStyle(button)
// confirm
print(label.layer.cornerRadius == 5) // true
print(label.backgroundColor == UIColor.white) // true
print(label.font == UIFont.systemFont(ofSize: 15)) // true
print(button.layer.cornerRadius == 10) // true
print(button.backgroundColor == UIColor.black) // true
print(button.titleColor(for: .normal) == UIColor.white) // true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment