Last active
March 28, 2023 09:25
-
-
Save martin-lalev/def33e0d3ee8861ee2a4c4d13a231da1 to your computer and use it in GitHub Desktop.
DSL for building UIView hierarchies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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