Skip to content

Instantly share code, notes, and snippets.

@crisrojas
Created February 3, 2023 00:21
Show Gist options
  • Save crisrojas/130e36ffddde91f8696d5ad081597304 to your computer and use it in GitHub Desktop.
Save crisrojas/130e36ffddde91f8696d5ad081597304 to your computer and use it in GitHub Desktop.
Simple demo counter implemented with the Khipu architecture
import SwiftUI
fileprivate var store = createRamStore()
fileprivate var viewState = ViewState(store: store)
fileprivate var rootHandler = createCore(store: store)
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView(
viewState: viewState,
rootHandler: rootHandler
)
}
}
}
enum Message {case increase ; case decrease}
typealias Input = (Message) -> Void
typealias Core = (Message) -> Void
struct AppState { let count: Int }
extension AppState { enum Change { case increase ; case decrease } }
extension AppState {
func alter(_ change: Change) -> Self {
switch change {
case .increase: return .init(count: count + 1)
case .decrease: return .init(count: count - 1)
}
}
}
typealias Change = (AppState.Change) -> Void
typealias Callback = (@escaping()->()) -> Void
typealias Access = ( ) -> AppState
typealias StateStore = (
state: Access,
change: Change,
updated: Callback
)
extension [()->()] { func call() {forEach {$0()}}}
func createRamStore() -> StateStore {
var state = AppState(count: 0) {didSet {
callbacks.call()
}}
var callbacks = [()->()]()
return (
state: { state },
change: { state = state.alter($0) },
updated: { callbacks.append($0) }
)
}
func createCore(store: StateStore) -> Core {{
if case .increase = $0 { store.change(.increase) }
if case .decrease = $0 { store.change(.decrease) }
}}
final class ViewState: ObservableObject {
@Published var count: Int?
init(store: StateStore) {
process(store.state())
store.updated {
self.process(store.state())
}
}
func process(_ state: AppState) {
count = state.count
}
}
struct ContentView: View {
@StateObject var viewState: ViewState
let rootHandler: Core
func increase() {rootHandler(.increase)}
func decrease() {rootHandler(.decrease)}
var body: some View {
if let count = viewState.count {
Stepper(
count.description,
onIncrement: increase,
onDecrement: decrease
)
.padding(.horizontal)
} else {
ProgressView()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment