Last active
June 15, 2023 03:02
-
-
Save markmals/6106c1e77b3d012057331339d0a0d6c9 to your computer and use it in GitHub Desktop.
My ideal Swift Macro version of a Solid.js-like renderer for UIKit via Swift
This file contains hidden or 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
import SwiftSignal | |
import FineGrainedViews | |
// Macro usage: | |
final class CounterViewController: UIViewController { | |
private let count = Signal(0) | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
self.view = #FineGrainedUIView { | |
UIStackView(axis: .vertical) { | |
UIButton(String(count.value)) { | |
count.value += 1 | |
} | |
.tintColor(count.value % 2 ? .systemRed : nil) | |
} | |
} | |
} | |
} | |
// Generated extensions using a Swift package plugin transforms | |
// the official UIKit API into its declarative counterpart | |
// as non-working extensions with the goal API. | |
// These APIs never actually get called in compiled code. | |
extension UIStackView { | |
init(axis: NSLayoutConstraint.Axis, @FineGrainedUIViewBuilder builder: () -> [UIView]) { | |
fatalError() | |
} | |
} | |
extension UIButton { | |
init(_ title: String, _ action: () -> Void) { | |
fatalError() | |
} | |
func tintColor(_ color: UIColor) -> Self { | |
fatalError() | |
} | |
} | |
// The macro generates: | |
final class CounterViewController: UIViewController { | |
private let count = Signal(0) | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
self.view = { | |
let button = UIButton( | |
primaryAction: UIAction { [unowned self] _ in | |
self.count.value += 1 | |
} | |
) | |
let stackView = UIStackView(arrangedSubviews: [button]) | |
stackView.axis = .vertical | |
effect { | |
button.setTitle(String(count.value)) | |
button.tintColor = count.value % 2 ? .systemRed : nil | |
} | |
return stackView | |
}() | |
} | |
} |
This file contains hidden or 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
// Macro usage: | |
@Component | |
class MyComponent { | |
let count = Signal(0) | |
var view: UIView { | |
UIStackView(axis: .vertical) { | |
UIButton(String(count.get())) { | |
count.update { $0 + 1 } | |
} | |
.tintColor(count.get() % 2 ? .systemRed : nil) | |
} | |
} | |
} | |
// Generated extensions using a Swift package plugin transforms | |
// the official UIKit API into its declarative counterpart | |
// as non-working extensions with the goal API. | |
// These APIs never actually get called in compiled code. | |
extension UIStackView { | |
init(axis: NSLayoutConstraint.Axis, @ComponentBuilder builder: () -> [UIView]) { | |
fatalError() | |
} | |
} | |
extension UIButton { | |
init(_ title: String, _ action: () -> Void) { | |
fatalError() | |
} | |
func tintColor(_ color: UIColor) -> Self { | |
fatalError() | |
} | |
} | |
// The macro generates: | |
class MyComponent { | |
let ref: EffectRef? | |
let count = Signal(0) | |
var view: UIView { | |
let button = UIButton( | |
primaryAction: UIAction { [unowned self] _ in | |
self.count.update { $0 + 1 } | |
} | |
) | |
let stackView = UIStackView(arrangedSubviews: [button]) | |
stackView.axis = .vertical | |
ref = effect { | |
button.setTitle(String(count.get())) | |
button.tintColor = count.get() % 2 ? .systemRed : nil | |
} | |
return stackView | |
} | |
deinit() { | |
ref?.destroy() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment