SwiftUI Alert

2021년 8월 23일 수정

SwiftUI에서 경고창을 띄우는 것은 약간 번거롭다. 함수를 호출해서 띄우는 방식이 아니라 스테이트 변화를 추적하도록 구현해야 하기 때문이다. 여기서는 이 경고창을 띄우는 간단한 방법을 정리한다.

isPresented를 이용해 Alert 다이얼로그 띄우기

가장 간단한 방법으로 Boolean 스테이트를 이용하는 방법이다.

struct ContentView: View {
    @State private var showingAlert = false

    var body: some View {
        Button("Show Alert") {
            showingAlert = true
        }
        .alert(isPresented: $showingAlert) {
            Alert(title: Text("Title"),
                  message: Text("Messages"),
                  primaryButton: .default(Text("Ok")) {
                      print("Ok!")
                  },
                  secondaryButton: .cancel() {
                      print("Canceled")
                  })
        }
    }
}

.default() 버튼 및 .cancel() 버튼의 경우 눌렸을 때의 반응을 처리하기 위한 두 번째 매개변수인 action 클로저를 반드시 구현할 필요는 없다. 즉 뒤의 중괄호 내용은 비어있어도 빌드 및 실행에는 문제가 없다. 하지만 아마도 확인과 취소 사이에 뭔가 기능 구현은 필요할 테니 알아두는 편이 좋을 것 같다.

Identifiable item을 이용해 Alert 다이얼로그 띄우기

위의 Boolean 스테이트 대신 Identifiable을 구현한 인스턴스의 값을 이용할 수도 있다.

struct AlertInfo: Identifiable {
    var id: Int
    let title: String
    let message: String
}

struct ContentView: View {
    @State private var alertInfo: AlertInfo?

    var body: some View {
        Button("Show Alert") {
            alertInfo = AlertInfo(id: 0,
                                  title: "Title",
                                  message: "Messages")
        }
        .alert(item: $alertInfo) { info in
            Alert(title: info.title,
                  message: info.message,
                  primaryButton: .default(Text("Ok")) {
                      print("Ok!")
                  },
                  secondaryButton: .cancel() {
                      print("Canceled")
                  })
        }
    }
}

이 방식은 경고 창의 문구가 여러 종류가 있을 경우 하나의 코드 만으로 사용하기 편할 것 같다.

버튼에 대한 추가 사항

.cancel() 버튼에도 별도의 원하는 텍스트나 뷰를 배치할 수 있다.

.cancel(Text("취소"))

Alert.Button은 아래 여러 종류가 있다.

  • .default(): 일반 버튼
  • .destructive(): 위험한 분위기를 풍기듯이 붉은색으로 강조된 버튼
  • .cancel(): 취소 버튼

기타

.alert 는 여러 항목을 동시에 정의하는 것도 가능하다.

Button("Show Alert 1") {
    showingAlert1 = true
}
Button("Show Alert 2") {
    showingAlert2 = true
}
.alert(isPresented: $showingAlert1) {
    ...
}
.alert(isPresented: $showingAlert2) {
    ...
}

아마도 아이템을 사용하는 방식과 동시에 사용하는 것도 가능하리라 생각된다.

관련된 주제들