Skip to content

Instantly share code, notes, and snippets.

@martin-lalev
Last active March 28, 2023 09:25
Show Gist options
  • Save martin-lalev/def33e0d3ee8861ee2a4c4d13a231da1 to your computer and use it in GitHub Desktop.
Save martin-lalev/def33e0d3ee8861ee2a4c4d13a231da1 to your computer and use it in GitHub Desktop.
DSL for building UIView hierarchies
precedencegroup HierarchyPrecedence {
lowerThan: AssignmentPrecedence
associativity: left
}
infix operator |--: HierarchyPrecedence
public protocol UIViewHierarchyProvider {
associatedtype View: UIView
var view: View { get }
var viewController: UIViewController? { get }
func append(_ view: UIView)
}
extension UIViewHierarchyProvider {
@discardableResult
public static func |-- <V:UIView> (lpred: Self, rpred: V) -> Self {
lpred.append(rpred)
return lpred
}
@discardableResult
public static func |-- <V:UIView> (lpred: Self, rpred: V?) -> Self {
guard let view = rpred else { return lpred }
lpred.append(view)
return lpred
}
@discardableResult
public static func |-- <V:UIView> (lpred: Self, rpred: [V]) -> Self {
for view in rpred { lpred.append(view) }
return lpred
}
@discardableResult
public static func |-- (lpred: Self, rpred: UIViewController) -> Self {
guard let parent = lpred.viewController else { return lpred }
parent.addChild(rpred)
lpred.append(rpred.view)
rpred.didMove(toParent: parent)
return lpred
}
}
public class UIViewHierarchy: UIViewHierarchyProvider {
public let view:UIView
public let viewController: UIViewController?
init(_ view:UIView, viewController: UIViewController?) {
self.view = view
self.viewController = viewController
}
public func append(_ view: UIView) {
self.view.addSubview(view)
}
}
public class UIStackViewHierarchy: UIViewHierarchyProvider {
public let view:UIStackView
public let viewController: UIViewController?
init(_ view:UIStackView, viewController: UIViewController?) {
self.view = view
self.viewController = viewController
}
public func append(_ view: UIView) {
self.view.addArrangedSubview(view)
}
}
extension UIView {
@discardableResult
public func hierarchy(in viewController: UIViewController? = nil, _ processer:(UIViewHierarchy)->Void) -> Self {
let h = UIViewHierarchy(self, viewController: viewController)
processer(h)
return self
}
}
extension UIStackView {
@discardableResult
public func arrangedHierarchy(in viewController: UIViewController? = nil, skipCleaning: Bool = false, _ processer:(UIStackViewHierarchy)->Void) -> Self {
if !skipCleaning {
while let view = self.subviews.first {
view.removeFromSuperview()
}
}
let h = UIStackViewHierarchy(self, viewController: viewController)
processer(h)
return self
}
}
extension UIViewController {
@discardableResult
public func hierarchy(_ processer:(UIViewHierarchy)->Void) -> Self {
let h = UIViewHierarchy(self.view, viewController: self)
processer(h)
return self
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment