Instantly share code, notes, and snippets.
Last active
December 3, 2022 21:58
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save taskcruncher/34a4ca10d1409dd8eff6f56410004860 to your computer and use it in GitHub Desktop.
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
// | |
// ContentView.swift | |
// scopetest | |
// | |
// Created by Steedman Bass on 11/6/22. | |
// | |
import ComposableArchitecture | |
import SwiftUI | |
@dynamicMemberLookup | |
struct TCASharedState<State: Equatable>: Equatable { | |
var sharedState: SharedState | |
var state: State | |
init(sharedState: SharedState, state: State){ | |
self.sharedState = sharedState | |
self.state = state | |
} | |
//https://www.swiftbysundell.com/tips/combining-dynamic-member-lookup-with-key-paths/ | |
subscript<T>(dynamicMember keyPath: WritableKeyPath<State, T>) -> T { | |
get { state[keyPath: keyPath] } | |
set { state[keyPath: keyPath] = newValue } | |
} | |
} | |
struct TCAApp: ReducerProtocol { | |
struct State: Equatable { | |
var sharedState: SharedState | |
var onlyPerson = Person() | |
var personState: PersonPlusSharedState.State { | |
get { | |
PersonPlusSharedState.State(baseState: TCASharedState(sharedState: sharedState, state: onlyPerson)) | |
} | |
set { | |
sharedState = newValue.baseState.sharedState | |
onlyPerson = newValue.baseState.state | |
} | |
} | |
var dog: Dog.State | |
} | |
enum Action: Equatable { | |
case dogAction(Dog.Action) | |
case personAction( PersonPlusSharedState.Action) | |
case changeOnlineStatus | |
} | |
var body: some ReducerProtocol<State, Action> { | |
Reduce{(state, action) -> Effect<Action, Never> in | |
switch action { | |
case .changeOnlineStatus: | |
state.sharedState.onlineStatus.online.toggle() | |
return .none | |
default: return .none | |
} | |
} | |
Scope(state: \State.personState, action: /Action.personAction) { | |
PersonPlusSharedState() | |
} | |
Scope(state: \State.dog, action: /Action.dogAction) { | |
Dog() | |
} | |
} | |
} | |
struct SharedState: Equatable { | |
var onlineStatus: OnlineStatus = OnlineStatus() | |
var simperium: Simperium = Simperium() | |
} | |
class DogColor: Equatable { | |
static func == (lhs: DogColor, rhs: DogColor) -> Bool { | |
lhs.color == rhs.color | |
} | |
var color = "Blue" | |
} | |
struct Simperium : Equatable { | |
var authToken = "aabb" | |
} | |
struct OnlineStatus: Equatable { | |
var online = false | |
} | |
struct PersonPlusSharedState: ReducerProtocol { | |
func reduce(into state: inout State, action: Action) -> EffectTask<Action> { | |
switch action { | |
case .updateName: if state.baseState.state.name == "bill" {state.baseState.state.name = "fred"} else {state.baseState.state.name = "bill"} | |
} | |
return .none | |
} | |
@dynamicMemberLookup | |
struct State: Equatable { | |
var baseState: TCASharedState<Person> | |
subscript<T>(dynamicMember keyPath: WritableKeyPath<TCASharedState<Person>, T>) -> T { | |
get { baseState[keyPath: keyPath] } | |
set { baseState[keyPath: keyPath] = newValue } | |
} | |
} | |
enum Action: Equatable { | |
case updateName | |
} | |
} | |
struct Person: Equatable { | |
var name = "Bob" | |
var age = 12 | |
enum Action: Equatable { | |
case updateName | |
} | |
} | |
struct Dog: ReducerProtocol { | |
func reduce(into state: inout State, action: Action) -> EffectTask<Action> { | |
switch action { | |
case let .changeName(name: name): state.name = name | |
default: break | |
} | |
return .none | |
} | |
struct State: Equatable { | |
var name = "Bob" | |
var age = "12" | |
var dogColor = DogColor() | |
} | |
enum Action: Equatable { | |
case changeName(name: String) | |
case changeColor(color: String) | |
} | |
} | |
struct PersonView: View { | |
let store: StoreOf<PersonPlusSharedState> | |
var body: some View { | |
WithViewStore(self.store, observe: {$0}){vs in | |
Text(vs.state.baseState.name) | |
} | |
} | |
} | |
struct ContentView: View { | |
let store: StoreOf<TCAApp> | |
var body: some View { | |
WithViewStore(self.store.scope(state: \.personState, action: {TCAApp.Action.personAction($0)})) {vs in | |
Text(vs.name) | |
Button("changeName", action: {vs.send(.updateName)}) | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment