-
-
Save nikitamounier/9ebfbbb2ff6a1362d889156472cd47d0 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
// https://github.com/apple/swift-evolution/blob/main/proposals/0258-property-wrappers.md#delayed-initialization | |
@propertyWrapper | |
struct DelayedImmutable<Value> { | |
private var _value: Value? = nil | |
var wrappedValue: Value { | |
get { | |
guard let value = _value else { | |
fatalError("property accessed before being initialized") | |
} | |
return value | |
} | |
// Perform an initialization, trapping if the | |
// value is already initialized. | |
set { | |
if _value != nil { | |
fatalError("property initialized twice") | |
} | |
_value = newValue | |
} | |
} | |
} | |
@propertyWrapper | |
struct WrappedStoreLocal<State, Action, LocalState>: DynamicProperty { | |
@DelayedImmutable var wrappedValue: Store<State, Action> | |
@DelayedImmutable @ObservedObject var projectedValue: ViewStore<LocalState, Action> | |
@DelayedImmutable private var viewState: (State) -> LocalState | |
@DelayedImmutable private var removeDuplicates: (LocalState, LocalState) -> Bool | |
init(viewState: @escaping (State) -> LocalState, removeDuplicates: @escaping (LocalState, LocalState) -> Bool) { | |
self.viewState = viewState | |
self.removeDuplicates = removeDuplicates | |
} | |
init(viewState: @escaping (State) -> LocalState) where LocalState: Equatable { | |
self.init(viewState: viewState, removeDuplicates: ==) | |
} | |
init(wrappedValue store: Store<State, Action>) { | |
self.wrappedValue = store | |
self.projectedValue = ViewStore(store.scope(state: viewState), removeDuplicates: removeDuplicates) | |
} | |
} | |
struct AppState: Equatable { | |
var string: String = .init() | |
var int: Int = .init() | |
} | |
enum AppAction {} | |
struct MyView: View { | |
struct ViewState: Equatable { | |
var string: String | |
init(state: AppState) { | |
self.string = state.string | |
} | |
} | |
@WrappedStoreLocal(viewState: ViewState.init) var store: Store<AppState, AppAction> | |
var body: some View { | |
Text($store.string) | |
} | |
} | |
struct ParentView: View { | |
@WrappedStore var store: Store<AppState, AppAction> | |
var body: some View { | |
MyView(store: <#T##Store<AppState, AppAction>#>) // what I'd like it to be | |
MyView(store: <#T##WrappedStoreLocal<AppState, AppAction, MyView.ViewState>#>) // what it actually wants | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment