Skip to content

Instantly share code, notes, and snippets.

@steipete
Created January 28, 2021 10:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steipete/3f61141f257aa1e056816c9cafded26d to your computer and use it in GitHub Desktop.
Save steipete/3f61141f257aa1e056816c9cafded26d to your computer and use it in GitHub Desktop.
with and then for UIKit and SwiftUI
/// Perform an immediate mutation of `subject`. The `transform` function may
/// just mutate the given `subject` or replace it entirely.
///
/// - Parameters:
/// - subject: A value to be transformed.
/// - transform: A closure that mutates or replaces the `subject`.
@inlinable func with<T>(_ subject: T, _ transform: (_ subject: inout T) throws -> Void) rethrows -> T {
var subject = subject
try transform(&subject)
return subject
}
// We use a global with, so the object-based one is called `then`.
protocol Thenable { /* no requirements */ }
extension Thenable {
/// Create a copy (if a struct) or use same object (if class), improving chainability e.g. after init method.
/// Example:
/// struct Foo: Thenable {
/// var bar: Int = 0
/// var baz: Bool = false
/// }
///
/// Make a copy of foo, overriding an arbitrary subset of properties
/// let foo2 = foo.then { $0.bar = 7; $0.baz = true }
///
/// Example then classes. This is especially useful if you want to use the auto return:
///
/// func getSettingsController() -> DocumentSettingsViewController {
/// DocumentSettingsViewController(style: UITableView.insetGroupStyle).then {
/// $0.title = localizedString(.Document_Presentation)
/// $0.pdfViewController = getPDFViewController()
/// $0.showsAllSettingsOptions = true
/// }
/// }
@discardableResult @inlinable func then(_ config: (inout Self) throws -> Void) rethrows -> Self {
return try with(self, config)
}
}
// Adopt `then` for any NSObject.
extension NSObject: Thenable { }
@available(iOS 13.0, *)
extension View {
/// Helper to simplify the copy, mutate and return pattern.
func then(_ body: (inout Self) -> Void) -> Self {
with(self, body)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment