Skip to content

Commit

Permalink
Merge pull request #42 from StevenLambion/features/remove-equatable-w…
Browse files Browse the repository at this point in the history
…hen-not-needed

Inject store by type
  • Loading branch information
StevenLambion authored May 12, 2020
2 parents 301cf38 + 96626c0 commit 0858ab1
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Sources/SwiftDux/UI/Connectable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import SwiftUI
/// to a possible bug in Swift that throws an invalid assocated type if Props isn't explicitly typealiased.
public protocol Connectable {

associatedtype Superstate: Equatable
associatedtype Superstate
associatedtype Props: Equatable

/// Causes the view to be updated based on a dispatched action.
Expand Down
9 changes: 4 additions & 5 deletions Sources/SwiftDux/UI/Connector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ internal final class NoUpdateAction: Action {

fileprivate let noUpdateAction = NoUpdateAction()

internal struct Connector<Content, Superstate, Props>: View where Superstate: Equatable, Props: Equatable, Content: View {
public struct Connector<Content, Superstate, Props>: View where Props: Equatable, Content: View {
@EnvironmentObject private var storeWrapper: StoreWrapper<Superstate>
@Environment(\.actionDispatcher) private var actionDispatcher

private var content: (Props) -> Content
private var filter: ((Action) -> Bool)?
private var mapProps: (Superstate, ActionBinder) -> Props?

private var store: Store<Superstate> {
private var store: StoreProxy<Superstate> {
storeWrapper.store
}

@usableFromInline internal init(
public init(
content: @escaping (Props) -> Content,
filter: ((Action) -> Bool)?,
mapProps: @escaping (Superstate, ActionBinder) -> Props?
Expand All @@ -31,7 +31,7 @@ internal struct Connector<Content, Superstate, Props>: View where Superstate: Eq
self.mapProps = mapProps
}

var body: some View {
public var body: some View {
ConnectorInner(content: content, initialProps: getProps(), propsPublisher: createPropsPublisher())
}

Expand Down Expand Up @@ -63,7 +63,6 @@ internal struct Connector<Content, Superstate, Props>: View where Superstate: Eq
internal struct ConnectorInner<Content, Props>: View where Props: Equatable, Content: View {
private var content: (Props) -> Content
private var propsPublisher: AnyPublisher<Props, Never>

@State private var props: Props?

internal init(content: @escaping (Props) -> Content, initialProps: Props?, propsPublisher: AnyPublisher<Props, Never>) {
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftDux/UI/MappedState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import SwiftUI
/// }
/// ```
@propertyWrapper
public struct MappedState<State>: DynamicProperty where State: Equatable {
public struct MappedState<State>: DynamicProperty {
@EnvironmentObject private var storeWrapper: StoreWrapper<State>

public var wrappedValue: State {
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftDux/UI/StoreWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import Combine
import SwiftUI

internal final class StoreWrapper<State>: ObservableObject {
let store: Store<State>
let store: StoreProxy<State>

init(store: Store<State>) {
init(store: StoreProxy<State>) {
self.store = store
}
}
31 changes: 27 additions & 4 deletions Sources/SwiftDux/UI/ViewModifiers/StoreProviderViewModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import Combine
import SwiftUI

/// A view modifier that injects a store into the environment.
public struct StoreProviderViewModifier<State>: ViewModifier where State: StateType {
public struct StoreProviderViewModifier<State>: ViewModifier {
private var storeWrapper: StoreWrapper<State>

@usableFromInline internal init(store: Store<State>) {
@usableFromInline internal init(store: StoreProxy<State>) {
self.storeWrapper = StoreWrapper(store: store)
}

Expand Down Expand Up @@ -33,12 +33,35 @@ extension View {
/// RootAppNavigation()
/// .provideStore(store)
/// }
///
/// }
/// ```
/// - Parameter store: The store object to inject.
/// - Returns: The modified view.
@inlinable public func provideStore<State>(_ store: Store<State>) -> some View where State: StateType {
return modifier(StoreProviderViewModifier<State>(store: store))
return modifier(StoreProviderViewModifier<State>(store: store.proxy(for: State.self)!))
}

/// Injects a store into the environment as a specific type.
///
/// This is useful if a protocol is used to retreive the state in a `ConnectableView`. It can be used multiple times
/// to provide support for protocols that the store might adhere to.
/// struct RootView: View {
/// // Passed in from the AppDelegate or SceneDelegate class.
/// var store: Store<AppState>
///
///
/// var body: some View {
/// RootAppNavigation()
/// .provideStore(store)
/// .provideStore(store, as: NavigationStateRoot.self)
/// }
/// }
/// ```
/// - Parameters:
/// - store: The store object to inject.
/// - type: A type that the store adheres to.
/// - Returns: The modified view.
@inlinable public func provideStore<State, Substate>(_ store: Store<State>, as type: Substate.Type) -> some View where State: StateType {
return modifier(StoreProviderViewModifier<Substate>(store: store.proxy(for: type.self)!))
}
}

0 comments on commit 0858ab1

Please sign in to comment.