개발/Swift

SwiftUI + TCA 활용 액션 시트 구현 confirmationDialog

덤벨로퍼 2025. 2. 7. 09:11

액션 시트 구현방법

confirmationDialog 활용한다

 .confirmationDialog(<#T##LocalizedStringKey#>, isPresented: <#T##Binding<Bool>#>, titleVisibility: <#T##Visibility#>, actions: <#T##(T) -> A#>)

이옵션을 사용해보자

첫번쨰 - 가장 먼저 타이틀 영역 (Stirng)

 

isPresented - 보여줄지 말지 Bool의 바인딩 값 (TCA 상태, 액션과 연결하면됨)

titleVisibility - 타이틀 영역 보여줄지

action - 여기서 버튼들을 생성해줌

isPresented 이거랑 action 만 잘 지정하면 될거같다

나머지는 알아서 세팅

 

일단 비교적 간단한 버튼구현 하여 버튼이 클릭되면

액션시트가 뜨는 방식으로 구현하려 한다.

 

만약 store에 리스트를 가지고 있고 그것을 활용한다면

ForEach를 사용해야 할것이다

 

그러면 또 Perception대응을 위해 WithPerceptionTracking 를 감싸야 한다 (안감싸면 에러)

https://dev-in-gym.tistory.com/275

 

그리고 각각의 버튼 액션을 집어 넣어주면 완성 (액션은 아래 구현)

actions: {
    ForEach(store.domainList, id:\\.self) { domain in
        WithPerceptionTracking {
            Button(action: { store.send(.selectEmailDomain(domain)) }) {
                Text(domain)
            }
        }
    }
}

이제 바인딩을 구현해야함

 

두가지가 필요하다

리듀서에서 Bool 상태, Bool 전달할 액션

enum Action {
    case presentActionSheet(Bool)
}
@ObservableState
struct State: Equatable {
    var presentActionSheet: Bool = false
}
   
   
// reducer
 case let .presentActionSheet(isPresent):
    state.presentActionSheet = isPresent

presentActionSheet 이라는 액션 상태를 만들어줬다.

리듀스 바디에 액션→ 상태 변경 코드도 구현

 

이제 isPresented에 넣어줌

isPresented: $store.presentActionSheet.sending(\\.presentActionSheet),

이게 이해가 안갈수 있는데 수정전에 내가 짰던 코드를 보면

isPresented: Binding(
    get: { store.presentActionSheet },
    set: { isPresented in
        if isPresented {
            store.send(.showActionSheet)
        } else {
            store.send(.hideActionSheet)
        }
    }
),

get 부분에 상태를 넣고

set에 액셔시트로 부터 전달받은 값(bool) 을 보고 액션을 취해 줬었다.

이거를 짧게 한 형태로 보면 된다.

store.presentActionSheet 이거를 get 하고
sending(\\.presentActionSheet) 이거를 set 해줌

전체 코드

  .confirmationDialog(Localized.actionSheetTitle,
                                isPresented: $store.presentActionSheet.sending(\\.presentActionSheet),
                                titleVisibility: .visible,
                                actions: {
                ForEach(store.domainList, id:\\.self) { domain in
                    WithPerceptionTracking {
                        Button(action: { store.send(.selectEmailDomain(domain)) }) {
                            Text(domain)
                        }
                    }
                }
            })