Skip to content

Instantly share code, notes, and snippets.

@nikitamounier
Created May 31, 2021 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikitamounier/9ebfbbb2ff6a1362d889156472cd47d0 to your computer and use it in GitHub Desktop.
Save nikitamounier/9ebfbbb2ff6a1362d889156472cd47d0 to your computer and use it in GitHub Desktop.
// 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