Skip to content

Instantly share code, notes, and snippets.

@cjndubisi
Created November 2, 2018 14:04
Show Gist options
  • Select an option

  • Save cjndubisi/f78d1104f136a437c0c09a5ebbde10e1 to your computer and use it in GitHub Desktop.

Select an option

Save cjndubisi/f78d1104f136a437c0c09a5ebbde10e1 to your computer and use it in GitHub Desktop.
UIViewStyling from Anatoli
import UIKit
import Foundation
/// An abstraction if `UIView` styling.
struct UIViewStyle<T: UIResponder> {
/// The styling function that takes a `UIView` instance
/// and performs side-effects on it.
public let styling: (T) -> Void
/// A factory method that composes multiple styles.
///
/// - Parameter styles: The styles to compose.
/// - Returns: A new `UIViewStyle` that will call the input styles'
/// `styling` method in succession.
static func compose(_ styles: UIViewStyle<T>...) -> UIViewStyle<T> {
return UIViewStyle { view in
for style in styles {
style.styling(view)
}
}
}
/// Compose this style with another.
///
/// - Parameter other: Other style to compose this style with.
/// - Returns: A new `UIViewStyle` which will call this style's `styling`,
/// and then the `other` style's `styling`.
func composing(with other: UIViewStyle<T>) -> UIViewStyle<T> {
return UIViewStyle { view in
self.styling(view)
other.styling(view)
}
}
/// Compose this style with another styling function.
///
/// - Parameter otherStyling: The function to compose this style with.
/// - Returns: A new `UIViewStyle` which will call this style's `styling`,
/// and then the input `styling`.
func composing(with otherStyling: @escaping (T) -> Void) -> UIViewStyle<T> {
return composing(with: UIViewStyle(styling: otherStyling))
}
/// Apply this style to a UIView.
///
/// - Parameter view: the view to style
func apply(to view: T) {
styling(view)
}
/// Apply this style to multiple views.
///
/// - Parameter views: the views to style
func apply(to views: T...) {
for view in views {
styling(view)
}
}
}
//extension Reactive where Base: UIResponder {
// var style: Binder<UIViewStyle<UIResponder>> {
// return Binder(base) { control, style in
// style.apply(to: control)
// }
// }
//}
protocol DesignableView: class {
var textColor: UIColor! { get set }
var font: UIFont! { get set }
var backgroundColor: UIColor? { set get }
static var configuration: DesignableConfiguration { get }
}
protocol DesignableConfiguration {
var big: CGFloat { get }
var base: CGFloat { get }
var small: CGFloat { get }
var semiBold: CGFloat { get }
var baseBold: CGFloat { get }
}
// the idea is to change it in one place and it changed every where
// with this you can change for only specific elements
extension DesignableConfiguration {
var big: CGFloat {
return 30 // alternative might be FontPalatte.title()
}
var base: CGFloat {
return 16 // alternative might be FontPalatte.body()
}
var small: CGFloat {
return 14 // etc
}
var semiBold: CGFloat {
return 16
}
var baseBold: CGFloat {
return 16
}
}
typealias DesignableViewUIResponder = DesignableView
extension UIViewStyle where T: DesignableViewUIResponder {
static func base(with size: CGFloat) -> UIViewStyle<T> {
return UIViewStyle(styling: { (d) in
d.backgroundColor = .white
})
}
/*
DO NO expose ad-hoc possibities
*/
private static func baseSemibold(with size: CGFloat) -> UIViewStyle<T> {
return UIViewStyle { textfield in
textfield.backgroundColor = UIColor.white
// textfield.font = Font.semibold(size)
}
}
private static func baseBold(with size: CGFloat) -> UIViewStyle<T> {
return UIViewStyle { textfield in
textfield.backgroundColor = UIColor.white
// textfield.font = Font.bold(size)
}
}
static var big: UIViewStyle<T> {
return base(with: T.configuration.big)
}
static var bigSemibold: UIViewStyle<T> {
return baseSemibold(with: T.configuration.big)
}
static var bigBold: UIViewStyle<T> {
return baseBold(with: T.configuration.big)
}
static var base: UIViewStyle<T> { return base(with: T.configuration.base) }
static var baseSemibold: UIViewStyle<T> { return baseSemibold(with: T.configuration.semiBold) }
static var baseBold: UIViewStyle<T> { return baseBold(with: T.configuration.baseBold) }
static var small: UIViewStyle<T> { return base(with: T.configuration.small) }
static var smallSemibold: UIViewStyle<T> { return baseSemibold(with: T.configuration.small) }
static var smallBold: UIViewStyle<T> { return baseBold(with: T.configuration.small) }
static var blue: UIViewStyle<T> {
return UIViewStyle { label in
label.textColor = .blue
}
}
static var darkGrey: UIViewStyle<T> {
return UIViewStyle { label in
label.textColor = .darkGray
}
}
static var grey: UIViewStyle<T> {
return UIViewStyle { label in
label.textColor = .gray
}
}
static var black: UIViewStyle<T>{
return UIViewStyle { label in
label.textColor = .black
}
}
static var white: UIViewStyle<T> {
return UIViewStyle { label in
label.textColor = .white
}
}
}
struct BaseUIConfiguation: DesignableConfiguration {}
struct UILabelConfiguation: DesignableConfiguration {}
struct UIButtonConfiguation: DesignableConfiguration {}
struct UITextFieldConfiguation: DesignableConfiguration {}
extension UILabel: DesignableView {
static var configuration: DesignableConfiguration {
return UILabelConfiguation()
}
}
extension UIButton: DesignableView {
var textColor: UIColor! {
get {
return titleColor(for: .normal)
}
set {
setTitleColor(newValue, for: .normal)
}
}
var font: UIFont! {
get {
return titleLabel?.font
}
set {
titleLabel?.font = newValue
}
}
static var configuration: DesignableConfiguration {
return BaseUIConfiguation()
}
}
// Use typealias for duplicated code style
typealias LabelStyle = UIViewStyle<UILabel>
typealias ButtonStyle = UIViewStyle<UIButton>
typealias UITextFieldStyle = UIViewStyle<UITextField>
LabelStyle.baseSemibold.apply(to: UILabel())
ButtonStyle.baseSemibold.apply(to: UIButton())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment