Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- widget
- 스유
- 웹
- 리액트
- 멋쟁이사자처럼
- uikit
- 네트워크
- swift concurrency
- SwiftUI
- spritekit
- 대외활동
- 1일1알골
- composable architecture
- Protocol
- 백준
- 컴퓨터그래픽스
- dispatchqueue
- c++
- 멋사
- 문법
- 운영체제
- 알고리즘
- TCA
- 영남대
- 스위프트
- 후기
- widgetkit
- 위젯킷
- cs
- Swift
Archives
- Today
- Total
맛동산이
SwiftUI) TCA- Effect에 대해서 본문
Effect는 Action을 통해서 동작할 동작들을 의미한다.
Effect에는 다음과 같은 동작들이 존재한다 .
- none: 즉시 완료
- run: 비동기 작업
- send: 전달된 Action을 즉시 내보냄
- cancel: 진행중인 Effect를 취소
- merge: 동시에 실행되는 단일 Effect로 병합
- concatenate: 차례로 실행되는 단일 Effect로 연결
- animation: SwiftUI의 .withAnimation
- transcation: SwiftUI의 .withTransaction
- debounce: debounce Effect로 변경
- throttle: trottle Effect로 변경
Effect는 기본적으로 단일의 행동을 하도록 하고, 여러 동작을 묶을수도 있으며, 연쇄적으로 동작할수도 있다.
예시 )
Reduce { state, action in
switch action {
case .onAppear:
return .concatenate([
.send(.request)
])
case .request:
return .run { send in
let response = await newsClient.request()
await send(.fetchResponse(response))
}
case let .fetchResponse(.success(newses)):
state.newses = newses
return .none
default:
return .none
}
Concatenate와 같은 타입 사용법
기존의 .none과 .run처럼 두개의 액션을 동시에 처리하거나, 순서대로 처리하거나 하는 동작에서
.merge와 .concat과 같은 방식으로 처리를 할수 있음
예시코드
Reduce { state, action in
switch action {
case .onAppear:
return .concatenate([
.send(.someActionFirst)
.send(.someActionAfter)
])
}
액션에 따른 Effect를 묶어주고, 해당 이펙트들이 다시 액션에서 동작하도록 묶어주는 역할을 하게 된다.
이를 통해서 api호출의 순서를 보장하거나, UI 업데이트의 순서를 보장하거나 할 수 있다.
자주 보는 에러
run 안에서는 state를 캡처링 할수 없기 때문에
case .factButtonTapped:
state.fact = nil
state.isLoading = true
let (data, _) = try await URLSession.shared
.data(from: URL(string: "<http://numbersapi.com/\\\\(state.count)>")!)
// 🛑 'async' call in a function that does not support concurrency
// 🛑 Errors thrown from here are not handled
state.fact = String(decoding: data, as: UTF8.self)
state.isLoading = false
return .none
이렇게 직접적으로 state의 값을 변경하려고 하면 에러가 발생한다 .
따라서 새로이 action을 정의하고, 해당 액션 안에서 받은 데이터를 통해서 State를 다시 업데이트 해주는 방식으로 처리해야한다.
해결방법 코드
case .factButtonTapped:
state.fact = nil
state.isLoading = true
return .run { send in
let (data, _) = try await URLSession.shared
.data(from: URL(string: "<http://numbersapi.com/\\\\(state.count)>")!)
let fact = String(decoding: data, as: UTF8.self)
send(.fetchData(fact)
}
case let .fetchData(fact):
state.fact = fact
state.isLoading = false
return .none
반응형
'앱 > SwiftUI' 카테고리의 다른 글
SwiftUI) TCA - Navigation하는 방법(Presents, PresentationAction, ifLet) (0) | 2024.09.17 |
---|---|
SwiftUI) TAC - NestedAction, Action의 가독성을 높이기 위한 방법 (2) | 2024.09.17 |
SwiftUI) TAC 에서 공유 데이터 사용하는법(shared Data), AsyncStream과 Shared State (0) | 2024.09.17 |
SwiftUI) TCA - ifLet, 옵셔널 State를 언래핑하는법 - 화면전환이 필요할때 (0) | 2024.09.17 |
SwiftUI) TCA 비동기처리, TaskResult타입 (0) | 2024.08.08 |