|
enum Action { |
|
|
|
case search(query: String) |
|
case signIn(name: String, email: String) |
|
case signOut |
|
} |
|
|
|
struct State { |
|
|
|
let name: String |
|
let email: String |
|
let searchQuery: String |
|
|
|
var isSignedIn: Bool { |
|
return name.isEmpty && email.isEmpty |
|
} |
|
|
|
static let initial = State(name: "", email: "", searchQuery: "") |
|
} |
|
|
|
struct Reducers { |
|
|
|
static func rootReducer(_ state: State, _ action: Action) -> State { |
|
return State( |
|
name: name(state, action), |
|
email: email(state, action), |
|
searchQuery: searchQuery(state, action) |
|
) |
|
} |
|
|
|
private static func name(_ state: State, _ action: Action) -> String { |
|
switch action { |
|
case .signIn(let name) |
|
return name |
|
|
|
case .signOut: |
|
return "" |
|
|
|
default: |
|
return state.name |
|
} |
|
} |
|
|
|
private static func email(_ state: State, _ action: Action) -> String { |
|
switch action { |
|
case .signIn(_, let email) |
|
return email |
|
|
|
case .signOut: |
|
return "" |
|
|
|
default: |
|
return state.email |
|
} |
|
} |
|
|
|
private static func searchQuery(_ state: State, _ action: Action) -> String { |
|
switch action { |
|
case .search(let query) |
|
return query |
|
|
|
default: |
|
return state.query |
|
} |
|
} |
|
} |
|
|
|
let store = Store(reducer: Reducers.root, state: .initial) |
|
|
|
store.observe(\.name) |
|
.subscribe(onNext: { name in |
|
// Update UI |
|
}) |
|
|
|
store.observe(\.searchQuery) |
|
.filter { !$0.isEmpty } |
|
.debounce(300) |
|
.flatMapLatest { searchQuery in |
|
// Perform search |
|
}) |
|
.subscribe(onNext: { searchResults in |
|
// Update UI |
|
}) |