Skip to content

Instantly share code, notes, and snippets.

@DanielCardonaRojas
Created November 20, 2019 16:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielCardonaRojas/270fa90e905b096216131aa27a388685 to your computer and use it in GitHub Desktop.
Save DanielCardonaRojas/270fa90e905b096216131aa27a388685 to your computer and use it in GitHub Desktop.
A small DSL to group and compose styles for UIKit components.
//
// Style.swift
// ComposableStyles
//
// Created by Daniel Cardona Rojas on 20/11/19.
// Copyright © 2019 Daniel Cardona Rojas. All rights reserved.
//
import UIKit
struct GenericStyle {
private let styling: (UIView) -> Void
init(_ styling: @escaping (UIView) -> Void) {
self.styling = styling
}
func apply(to view: UIView) {
styling(view)
}
}
struct Style<T: UIView> {
private let styling: (T) -> Void
init(_ styling: @escaping (T) -> Void) {
self.styling = styling
}
func apply(to view: T) {
styling(view)
}
}
// MARK: Shorthand helpers
extension Style {
static func property<P>(_ keyPath: ReferenceWritableKeyPath<T,P>, value: P) -> Style {
return Style { v in
v[keyPath: keyPath] = value
}
}
static func adjustingProperty<P>(_ keyPath: ReferenceWritableKeyPath<T,P>) -> (P) -> Style {
return { (value: P) in
Style { v in v[keyPath: keyPath] = value }
}
}
}
extension GenericStyle {
static func property<P>(_ keyPath: ReferenceWritableKeyPath<UIView,P>, value: P) -> GenericStyle {
return GenericStyle { v in
v[keyPath: keyPath] = value
}
}
static func adjustingProperty<P>(_ keyPath: ReferenceWritableKeyPath<UIView,P>) -> (P) -> GenericStyle {
return { (value: P) in
GenericStyle { v in v[keyPath: keyPath] = value }
}
}
}
// MARK: Combining styles
func +<V>(_ lhs: Style<V>, rhs: Style<V>) -> Style<V> {
return Style { (v: V) -> Void in
lhs.apply(to: v)
rhs.apply(to: v)
}
}
func +<V>(_ lhs: Style<V>, rhs: GenericStyle) -> Style<V> {
return Style { (v: V) -> Void in
lhs.apply(to: v)
rhs.apply(to: v)
}
}
func +<V>(_ lhs: GenericStyle, rhs: Style<V>) -> Style<V> {
return Style { (v: V) -> Void in
lhs.apply(to: v)
rhs.apply(to: v)
}
}
func +(_ lhs: GenericStyle, rhs: GenericStyle) -> GenericStyle {
return GenericStyle { (v: UIView) -> Void in
lhs.apply(to: v)
rhs.apply(to: v)
}
}
// MARK: Component Specific helpers
extension UIView {
func applying(_ style: GenericStyle) {
style.apply(to: self)
}
}
extension UILabel {
func applying(_ style: Style<UILabel>) {
style.apply(to: self)
}
}
extension UIButton {
func applying(_ style: Style<UIButton>) {
style.apply(to: self)
}
}
extension UICollectionViewCell {
func applying(_ style: Style<UICollectionViewCell>) {
style.apply(to: self)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment