์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
- ๋ฐฑ์ค
- SnapKit
- raywenderlich
- Lv2
- reactorkit
- XCTest
- visionOS
- Kuring
- arkit
- designpattern
- ios
- Xcode
- tableView
- RxSwift
- combine
- Swfit
- SwiftUI
- CollectionView
- BFS
- UIKit
- MVVM
- swift
- BOJ
- TCA
- Flutter
- node.js
- realm
- ํ๋ก๊ทธ๋๋จธ์ค
- ํจ์คํธ์บ ํผ์ค
- rxcocoa
- Today
- Total
lgvv98
[TCA] Effect #2 (Cancellation) ๋ณธ๋ฌธ
[TCA] Effect #1 (Cancellation)
๋ชฉ์ฐจ
- ํด๋น ์์ ์ ๊ด๋ จํ ์ค๋ช
- ํด๋น ์์ ์ฝ๋
# ํด๋น ์์ ์ ๊ด๋ จํ ์ค๋ช
This screen demonstrates how one can cancel in-flight effects in the Composable Architecture.
Use the stepper to count to a number, and then tap the "Number fact" button to fetch a random fact about that number using an API.
While the API request is in-flight, you can tap "Cancel" to cancel the effect and prevent it from feeding data back into the application. Interacting with the stepper while a request is in-flight will also cancel it.
์ด๋ฒ์๋ Effect๋ฅผ ์ทจ์ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ๋ณด์
๋ฒํผ์ ๋๋ฌ API๋ฅผ ์์ฒญ์ ์ซ์์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
์ฆ, ํ๋ก์ฐ๋ฅผ ์ ๋ฆฌํ์๋ฉด
๋ฒํผ ํด๋ฆญ -> API ์์ฒญ -> ์ด๋ ์ทจ์ -> API ์๋ต์ ๋ฐ์ง ์์
# ํด๋น ์์ ์ฝ๋
// MARK: - Feature domain
struct EffectsCancellation: Reducer {
struct State: Equatable {
var count = 0
var currentFact: String?
var isFactRequestInFlight = false
}
enum Action: Equatable {
case cancelButtonTapped
case stepperChanged(Int)
case factButtonTapped
case factResponse(TaskResult<String>)
}
@Dependency(\.factClient) var factClient
private enum CancelID { case factRequest }
func reduce(into state: inout State, action: Action) -> Effect<Action> {
switch action {
case .cancelButtonTapped:
state.isFactRequestInFlight = false
return .cancel(id: CancelID.factRequest) // factRequest ์บ์ฌ
case let .stepperChanged(value):
state.count = value
state.currentFact = nil
state.isFactRequestInFlight = false
return .cancel(id: CancelID.factRequest) // factRequest ์บ์ฌ
case .factButtonTapped:
state.currentFact = nil
state.isFactRequestInFlight = true
return .run { [count = state.count] send in
await send(.factResponse(TaskResult { try await self.factClient.fetch(count) }))
}
.cancellable(id: CancelID.factRequest) // ์บ์ฌ ๋ฑ๋ก Combine์ store(in: $cancellables) ๋ฐฉ์๊ณผ ๋์ผ
case let .factResponse(.success(response)):
state.isFactRequestInFlight = false
state.currentFact = response
return .none
case .factResponse(.failure):
state.isFactRequestInFlight = false
return .none
}
}
}
// MARK: - Feature view
struct EffectsCancellationView: View {
let store: StoreOf<EffectsCancellation>
@Environment(\.openURL) var openURL
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
Form {
Section {
AboutView(readMe: readMe)
}
Section {
Stepper(
"\(viewStore.count)",
value: viewStore.binding(get: \.count, send: EffectsCancellation.Action.stepperChanged)
)
if viewStore.isFactRequestInFlight {
HStack {
Button("Cancel") { viewStore.send(.cancelButtonTapped) }
Spacer()
ProgressView()
.id(UUID()) // SwiftUI ๋ฒ๊ทธ๋ก ๋ณด์ด๋๋ฐ id ์์ผ๋ฉด ๋๋ฒ์งธ ํธ๋ฆฌ๊ฑฐ ์์ ๋ถํฐ๋ ๋ณด์ด์ง ์๋ ์ด์
}
} else {
Button("Number fact") { viewStore.send(.factButtonTapped) }
.disabled(viewStore.isFactRequestInFlight)
}
viewStore.currentFact.map {
Text($0).padding(.vertical, 8)
}
}
Section {
Button("Number facts provided by numbersapi.com") {
self.openURL(URL(string: "http://numbersapi.com")!)
}
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity)
}
}
.buttonStyle(.borderless)
}
.navigationTitle("Effect cancellation")
}
}
// MARK: - SwiftUI previews
struct EffectsCancellation_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
EffectsCancellationView(
store: Store(initialState: EffectsCancellation.State()) {
EffectsCancellation()
}
)
}
}
}
Combine์ ์ฃผ๋ก ์ฌ์ฉํ๊ณ ์๋๋ฐ TCA์์ ์ฌ์ฉํ๋ ์ด๋ฐ ๊ฐ๋ ๋ค์ด ์ ๋ง ์์ ์ดํด๊ฐ๊ณ ์ ๋ง๋ค์๋ค๋ ์๊ฐ์ด ๋ ๋ค!!
'apple > ๐ฆฅ TCA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[TCA] Effect #4 (Refreshable) (0) | 2023.10.07 |
---|---|
[TCA] Effect #3 (LongLiving) (0) | 2023.10.07 |
[TCA] Effect #1 (Basics) (1) | 2023.10.07 |
[TCA] SharedState (1) | 2023.09.27 |
[TCA] OptionalState (IfLetCase) (0) | 2023.09.27 |