Skip to content

Instantly share code, notes, and snippets.

@janodev
Created September 29, 2020 18:08
Show Gist options
  • Save janodev/b62188b55fd576eaf5f1490472259313 to your computer and use it in GitHub Desktop.
Save janodev/b62188b55fd576eaf5f1490472259313 to your computer and use it in GitHub Desktop.
VFL example
import UIKit
final class SomeView: LayoutView
{
let view1 = UIView()
let view2 = UIView()
let view3 = UIView()
override func layout() {
super.layout()
autoLayout.applyVisualFormatLanguage([
"|-(30)-[view1]-(30)-[view2]-(30)-[view3]"
])
}
}
class LayoutView: UIView
{
override init(frame: CGRect) {
super.init(frame: frame)
layout()
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
layout()
}
func layout() {
autoLayout.enumerateSubViews().values.forEach { addSubview($0) }
}
}
public extension UIView {
var autoLayout: AutoLayout {
AutoLayout(self)
}
}
public struct AutoLayout {
public let base: UIView
public init(_ base: UIView) {
self.base = base
}
public func applyVisualFormatLanguage(_ constraints: [String],
options: NSLayoutConstraint.FormatOptions = [],
metrics: [String: Any]? = nil) {
base.translatesAutoresizingMaskIntoConstraints = false
var views = enumerateSubViews()
views["baseView"] = base
views.values.forEach { $0.translatesAutoresizingMaskIntoConstraints = false }
constraints.forEach {
base.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: $0, options: options, metrics: metrics, views: views))
}
}
/// Returns every non nil instance UIView variable in the given view, indexed by its variable name.
public func enumerateSubViews() -> [String: UIView] {
var views = [String: UIView]()
let mirror = Mirror(reflecting: base)
let addToViewsClosure: ((Mirror.Child) -> Void) = { child in
child.label.flatMap { label in
// lazy var has $__lazy_storage_$_ (swift 5.1+) and .storage (swift 5-) in `label` property.
#if swift(>=5.1)
let key = label.replacingOccurrences(of: "$__lazy_storage_$_", with: "")
#else
let key = label.replacingOccurrences(of: ".storage", with: "")
#endif
views[key] = child.value as? UIView
}
}
mirror.children.forEach(addToViewsClosure)
mirror.superclassMirror?.children.forEach(addToViewsClosure)
return views
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment