mirror of
https://github.com/pointfreeco/swift-composable-architecture.git
synced 2025-12-20 09:11:33 +01:00
NavigateAndLoad: Cancel loading on dismiss (#757)
* NavigateAndLoad: Cancel loading on dismiss * Update Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-NavigateAndLoad.swift Co-authored-by: Stephen Celis <stephen.celis@gmail.com> * Update Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-Sheet-PresentAndLoad.swift Co-authored-by: Stephen Celis <stephen.celis@gmail.com> * Add cancellation to UIKitCaseStudies/NavigateAndLoad.swift * Add cancellation to LoadThenNavigate studies Co-authored-by: Stephen Celis <stephen.celis@gmail.com>
This commit is contained in:
@@ -26,6 +26,7 @@ struct LoadThenNavigateListState: Equatable {
|
|||||||
|
|
||||||
enum LoadThenNavigateListAction: Equatable {
|
enum LoadThenNavigateListAction: Equatable {
|
||||||
case counter(CounterAction)
|
case counter(CounterAction)
|
||||||
|
case onDisappear
|
||||||
case setNavigation(selection: UUID?)
|
case setNavigation(selection: UUID?)
|
||||||
case setNavigationSelectionDelayCompleted(UUID)
|
case setNavigationSelectionDelayCompleted(UUID)
|
||||||
}
|
}
|
||||||
@@ -57,6 +58,9 @@ let loadThenNavigateListReducer =
|
|||||||
case .counter:
|
case .counter:
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
case .onDisappear:
|
||||||
|
return .cancel(id: CancelId())
|
||||||
|
|
||||||
case let .setNavigation(selection: .some(navigatedId)):
|
case let .setNavigation(selection: .some(navigatedId)):
|
||||||
for row in state.rows {
|
for row in state.rows {
|
||||||
state.rows[id: row.id]?.isActivityIndicatorVisible = row.id == navigatedId
|
state.rows[id: row.id]?.isActivityIndicatorVisible = row.id == navigatedId
|
||||||
@@ -119,6 +123,7 @@ struct LoadThenNavigateListView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitle("Load then navigate")
|
.navigationBarTitle("Load then navigate")
|
||||||
|
.onDisappear { viewStore.send(.onDisappear) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ struct LoadThenNavigateState: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum LoadThenNavigateAction: Equatable {
|
enum LoadThenNavigateAction: Equatable {
|
||||||
|
case onDisappear
|
||||||
case optionalCounter(CounterAction)
|
case optionalCounter(CounterAction)
|
||||||
case setNavigation(isActive: Bool)
|
case setNavigation(isActive: Bool)
|
||||||
case setNavigationIsActiveDelayCompleted
|
case setNavigationIsActiveDelayCompleted
|
||||||
@@ -38,12 +39,20 @@ let loadThenNavigateReducer =
|
|||||||
with: Reducer<
|
with: Reducer<
|
||||||
LoadThenNavigateState, LoadThenNavigateAction, LoadThenNavigateEnvironment
|
LoadThenNavigateState, LoadThenNavigateAction, LoadThenNavigateEnvironment
|
||||||
> { state, action, environment in
|
> { state, action, environment in
|
||||||
|
|
||||||
|
struct CancelId: Hashable {}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
|
|
||||||
|
case .onDisappear:
|
||||||
|
return .cancel(id: CancelId())
|
||||||
|
|
||||||
case .setNavigation(isActive: true):
|
case .setNavigation(isActive: true):
|
||||||
state.isActivityIndicatorVisible = true
|
state.isActivityIndicatorVisible = true
|
||||||
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
||||||
.delay(for: 1, scheduler: environment.mainQueue)
|
.delay(for: 1, scheduler: environment.mainQueue)
|
||||||
.eraseToEffect()
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId())
|
||||||
|
|
||||||
case .setNavigation(isActive: false):
|
case .setNavigation(isActive: false):
|
||||||
state.optionalCounter = nil
|
state.optionalCounter = nil
|
||||||
@@ -90,6 +99,7 @@ struct LoadThenNavigateView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onDisappear { viewStore.send(.onDisappear) }
|
||||||
}
|
}
|
||||||
.navigationBarTitle("Load then navigate")
|
.navigationBarTitle("Load then navigate")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,17 +37,19 @@ let navigateAndLoadReducer =
|
|||||||
with: Reducer<
|
with: Reducer<
|
||||||
NavigateAndLoadState, NavigateAndLoadAction, NavigateAndLoadEnvironment
|
NavigateAndLoadState, NavigateAndLoadAction, NavigateAndLoadEnvironment
|
||||||
> { state, action, environment in
|
> { state, action, environment in
|
||||||
|
struct CancelId: Hashable {}
|
||||||
switch action {
|
switch action {
|
||||||
case .setNavigation(isActive: true):
|
case .setNavigation(isActive: true):
|
||||||
state.isNavigationActive = true
|
state.isNavigationActive = true
|
||||||
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
||||||
.delay(for: 1, scheduler: environment.mainQueue)
|
.delay(for: 1, scheduler: environment.mainQueue)
|
||||||
.eraseToEffect()
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId())
|
||||||
|
|
||||||
case .setNavigation(isActive: false):
|
case .setNavigation(isActive: false):
|
||||||
state.isNavigationActive = false
|
state.isNavigationActive = false
|
||||||
state.optionalCounter = nil
|
state.optionalCounter = nil
|
||||||
return .none
|
return .cancel(id: CancelId())
|
||||||
|
|
||||||
case .setNavigationIsActiveDelayCompleted:
|
case .setNavigationIsActiveDelayCompleted:
|
||||||
state.optionalCounter = CounterState()
|
state.optionalCounter = CounterState()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ struct LoadThenPresentState: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum LoadThenPresentAction {
|
enum LoadThenPresentAction {
|
||||||
|
case onDisappear
|
||||||
case optionalCounter(CounterAction)
|
case optionalCounter(CounterAction)
|
||||||
case setSheet(isPresented: Bool)
|
case setSheet(isPresented: Bool)
|
||||||
case setSheetIsPresentedDelayCompleted
|
case setSheetIsPresentedDelayCompleted
|
||||||
@@ -38,12 +39,20 @@ let loadThenPresentReducer =
|
|||||||
with: Reducer<
|
with: Reducer<
|
||||||
LoadThenPresentState, LoadThenPresentAction, LoadThenPresentEnvironment
|
LoadThenPresentState, LoadThenPresentAction, LoadThenPresentEnvironment
|
||||||
> { state, action, environment in
|
> { state, action, environment in
|
||||||
|
|
||||||
|
struct CancelId: Hashable {}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
|
|
||||||
|
case .onDisappear:
|
||||||
|
return .cancel(id: CancelId())
|
||||||
|
|
||||||
case .setSheet(isPresented: true):
|
case .setSheet(isPresented: true):
|
||||||
state.isActivityIndicatorVisible = true
|
state.isActivityIndicatorVisible = true
|
||||||
return Effect(value: .setSheetIsPresentedDelayCompleted)
|
return Effect(value: .setSheetIsPresentedDelayCompleted)
|
||||||
.delay(for: 1, scheduler: environment.mainQueue)
|
.delay(for: 1, scheduler: environment.mainQueue)
|
||||||
.eraseToEffect()
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId())
|
||||||
|
|
||||||
case .setSheet(isPresented: false):
|
case .setSheet(isPresented: false):
|
||||||
state.optionalCounter = nil
|
state.optionalCounter = nil
|
||||||
@@ -93,6 +102,7 @@ struct LoadThenPresentView: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
.navigationBarTitle("Load and present")
|
.navigationBarTitle("Load and present")
|
||||||
|
.onDisappear { viewStore.send(.onDisappear) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,17 +35,19 @@ let presentAndLoadReducer =
|
|||||||
with: Reducer<
|
with: Reducer<
|
||||||
PresentAndLoadState, PresentAndLoadAction, PresentAndLoadEnvironment
|
PresentAndLoadState, PresentAndLoadAction, PresentAndLoadEnvironment
|
||||||
> { state, action, environment in
|
> { state, action, environment in
|
||||||
|
struct CancelId: Hashable {}
|
||||||
switch action {
|
switch action {
|
||||||
case .setSheet(isPresented: true):
|
case .setSheet(isPresented: true):
|
||||||
state.isSheetPresented = true
|
state.isSheetPresented = true
|
||||||
return Effect(value: .setSheetIsPresentedDelayCompleted)
|
return Effect(value: .setSheetIsPresentedDelayCompleted)
|
||||||
.delay(for: 1, scheduler: environment.mainQueue)
|
.delay(for: 1, scheduler: environment.mainQueue)
|
||||||
.eraseToEffect()
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId())
|
||||||
|
|
||||||
case .setSheet(isPresented: false):
|
case .setSheet(isPresented: false):
|
||||||
state.isSheetPresented = false
|
state.isSheetPresented = false
|
||||||
state.optionalCounter = nil
|
state.optionalCounter = nil
|
||||||
return .none
|
return .cancel(id: CancelId())
|
||||||
|
|
||||||
case .setSheetIsPresentedDelayCompleted:
|
case .setSheetIsPresentedDelayCompleted:
|
||||||
state.optionalCounter = CounterState()
|
state.optionalCounter = CounterState()
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ struct LazyNavigationState: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum LazyNavigationAction: Equatable {
|
enum LazyNavigationAction: Equatable {
|
||||||
|
case onDisappear
|
||||||
case optionalCounter(CounterAction)
|
case optionalCounter(CounterAction)
|
||||||
case setNavigation(isActive: Bool)
|
case setNavigation(isActive: Bool)
|
||||||
case setNavigationIsActiveDelayCompleted
|
case setNavigationIsActiveDelayCompleted
|
||||||
@@ -30,12 +31,16 @@ let lazyNavigationReducer =
|
|||||||
with: Reducer<
|
with: Reducer<
|
||||||
LazyNavigationState, LazyNavigationAction, LazyNavigationEnvironment
|
LazyNavigationState, LazyNavigationAction, LazyNavigationEnvironment
|
||||||
> { state, action, environment in
|
> { state, action, environment in
|
||||||
|
struct CancelId: Hashable {}
|
||||||
switch action {
|
switch action {
|
||||||
|
case .onDisappear:
|
||||||
|
return .cancel(id: CancelId())
|
||||||
case .setNavigation(isActive: true):
|
case .setNavigation(isActive: true):
|
||||||
state.isActivityIndicatorHidden = false
|
state.isActivityIndicatorHidden = false
|
||||||
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
||||||
.delay(for: 1, scheduler: environment.mainQueue)
|
.delay(for: 1, scheduler: environment.mainQueue)
|
||||||
.eraseToEffect()
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId())
|
||||||
case .setNavigation(isActive: false):
|
case .setNavigation(isActive: false):
|
||||||
state.optionalCounter = nil
|
state.optionalCounter = nil
|
||||||
return .none
|
return .none
|
||||||
@@ -120,6 +125,11 @@ class LazyNavigationViewController: UIViewController {
|
|||||||
@objc private func loadOptionalCounterTapped() {
|
@objc private func loadOptionalCounterTapped() {
|
||||||
self.viewStore.send(.setNavigation(isActive: true))
|
self.viewStore.send(.setNavigation(isActive: true))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidDisappear(_ animated: Bool) {
|
||||||
|
super.viewDidDisappear(animated)
|
||||||
|
self.viewStore.send(.onDisappear)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LazyNavigationViewController_Previews: PreviewProvider {
|
struct LazyNavigationViewController_Previews: PreviewProvider {
|
||||||
|
|||||||
@@ -30,16 +30,20 @@ let eagerNavigationReducer =
|
|||||||
with: Reducer<
|
with: Reducer<
|
||||||
EagerNavigationState, EagerNavigationAction, EagerNavigationEnvironment
|
EagerNavigationState, EagerNavigationAction, EagerNavigationEnvironment
|
||||||
> { state, action, environment in
|
> { state, action, environment in
|
||||||
|
|
||||||
|
struct CancelId: Hashable {}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .setNavigation(isActive: true):
|
case .setNavigation(isActive: true):
|
||||||
state.isNavigationActive = true
|
state.isNavigationActive = true
|
||||||
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
return Effect(value: .setNavigationIsActiveDelayCompleted)
|
||||||
.delay(for: 1, scheduler: environment.mainQueue)
|
.delay(for: 1, scheduler: environment.mainQueue)
|
||||||
.eraseToEffect()
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId())
|
||||||
case .setNavigation(isActive: false):
|
case .setNavigation(isActive: false):
|
||||||
state.isNavigationActive = false
|
state.isNavigationActive = false
|
||||||
state.optionalCounter = nil
|
state.optionalCounter = nil
|
||||||
return .none
|
return .cancel(id: CancelId())
|
||||||
case .setNavigationIsActiveDelayCompleted:
|
case .setNavigationIsActiveDelayCompleted:
|
||||||
state.optionalCounter = CounterState()
|
state.optionalCounter = CounterState()
|
||||||
return .none
|
return .none
|
||||||
|
|||||||
Reference in New Issue
Block a user