HIT해

[iOS/SwiftUI] TCA finish() 알아보기 본문

Swift/Swift CS

[iOS/SwiftUI] TCA finish() 알아보기

힛해 2024. 8. 30. 22:07
728x90

store.send().finish() vs store.send()

  • store.send():
    • 이 코드는 TCA(Typically Composable Architecture)에서 액션을 스토어로 전송한다.
    • 기본적으로 이 메서드는 비동기 작업을 시작하고, 해당 액션이 처리되는 동안의 작업을 관리하지 않는다.
  • store.send().finish():
    • finish()는 send(_:) 메서드가 반환하는 Effect의 메서드.
    • finish()는 해당 액션이 완료되었음을 나타내는 신호를 보낸다

finish의 역할

  • 비동기 작업의 완료 신호:
    • finish()는 비동기 작업이 완료되었음을 나타내는 신호를 보낸다.
    • 비동기 효과가 끝났을 때, 상태를 업데이트하거나 후속 작업을 처리하는 데 사용된다.
  • 상태 동기화:
    • 액션이 완료된 후, 상태가 올바르게 동기화되도록 보장한다.
    • 이는 비동기 작업이 완료된 후의 상태 업데이트를 처리하는 데 중요하다.
  • TCA의 효과 처리:
    • TCA에서는 비동기 작업을 관리하기 위해 Effect를 사용합니다.
    • finish()는 이 Effect가 완료되었음을 TCA에 알리는 방법입니다.
    • 이를 통해 상태가 최신 상태로 유지되고, 추가적인 후속 작업이 수행될 수 있습니다.

 

예제 코드

다음은 finish()를 사용하는 예제

// 비동기 작업을 수행하고 완료를 기다리는 액션
await store.send(.refresh).finish()

 

이 예제에서, .refresh 액션이 비동기 작업을 시작하고, finish()를 호출하여 비동기 작업이 완료될 때까지 기다린다.

이로 인해 상태가 올바르게 업데이트되고, 후속 작업이 진행되게 한다.

 

 

TCA Example_Refreshable 예시코드로 차이를 알아보자

 

finish를 사용할때

      if self.isLoading {
        Button("Cancel") {
          store.send(.cancelButtonTapped, animation: .default)
        }
      }
    }
    .refreshable {
      isLoading = true
      defer { isLoading = false }
      await store.send(.refresh).finish()
    }

 

 

 

 

 

 

finish 만 제거한 경우

.refreshable {
      isLoading = true
      defer { isLoading = false }
      await store.send(.refresh)
    }

 

 

.

 

 

 

defer 제거 & finish 를 사용한경우

   if self.isLoading {
        Button("Cancel") {
          store.send(.cancelButtonTapped, animation: .default)
        }
      }
    }
    .refreshable {
      isLoading = true
      await store.send(.refresh).finish()
    }

 

 

.

 

 

왜 이런 차이가 있는걸까.

TCA에서 UI 상태변화는 Reducer의 State값에 변경이 있을때만 일어난다.

.none 과 .run 은 액션이후 어떤 행동을 할지에 대한 정의만 할 뿐 상태 업데이트와는 아무런 연관이 없다.

 

이떄 Cancel 블록은 뷰 아래에 정의한 @State isLoading 의 Bool 값에 의해 표시할지 결정된다.

 

아무리 defer에서 isLoading을 토글해주었지만 SwiftUI에서 인식하기에는 너무 빠른 시간이다.

 

그래서 await에 finish를 붙여 확실히 끝났을때 비동기함수를 끝내주어 defer까지 오는 시간을 벌어주는 것으로 추측된다.