본문 바로가기

SwiftUI에서 경고창(Alert Dialog) 띄우기(iOS 15, macOS Monterey)

기술적인 이야기/애플 플랫폼 개발 2021. 10. 8.
반응형

iOS 15와 macOS Monterey에서 구현할 수 있는 SwiftUI용 경고창(Alert Dialog)을 띄우는 방법이 새로 추가되었다. 새 방법이 아무래도 코드가 더 간결한 것 같아서 정리해본다.

가장 기본적인 경고창 예제

가장 기본적으로 제목과 메시지 그리고 확인 버튼 하나가 있는 경고창을 띄우는 예제 코드는 아래와 같은 식이다.

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

    var body: some View {
        Button("Show Alert") {
            showingAlert = true
        }
        .alert("Alert Title", isPresented: $showingAlert) {
            Button("Ok") {}
        } message: {
            Text("This is alert dialog sample")
        }
    }
}

이전 방식과 동일하게 View가 경고창 표시 여부를 저장하는 Boolean 프로퍼티 하나를 가지게 되고 이 프로퍼티의 값을 토글 하는 것으로 경고창을 띄울 수 있다.

어쨌든 위 예제에서 핵심은 이 부분이다.

.alert("Alert Title", isPresented: $showingAlert) {
    Button("Ok") {}
} message: {
    Text("This is alert dialog sample")
}

message 필드의 내용으로 봐서 텍스트가 아닌 모든 뷰를 올릴 수 있을 것으로 유추된다. 하지만 대부분은 여기에 메시지 텍스트를 넣는 용도로 많이 쓰일 것 같다.

위 코드를 실행시키고 버튼이 눌려서 showingAlert 프로퍼티가 true가 되면 아래와 같은 경고창이 뜬다.

가장 기본적인 경고창의 모습

버튼을 누르면 지정된 핸들러 - 여기서는 아무런 기능을 하지 않게 중괄호 {} 내부가 비어있다 - 가 호출된다. 따라서 원하는 기능을 작성하기만 하면 된다. 그리고 이 핸들러가 호출될 때 지정된 프로퍼티 즉 showingAlert 프로퍼티의 값은 자동으로 false로 바뀐다.

참고로 스크린샷은 iOS 15 시뮬레이터에서 캡처한 모습인데 macOS에서는 데스크탑 앱에 맞는 형태로 표시될 뿐 코드는 동일하게 사용할 수 있다.

취소 버튼

취소(Cancel) 버튼을 수작업으로 만들 때는 버튼에 역할(role)을 지정할 수 있다.

.alert("Alert Title", isPresented: $showingAlert) {
    Button("Cancel", role: .cancel) {}
} message: {
    Text("This is alert dialog sample")
}

이렇게 하면 경고창의 버튼 스타일이 아래처럼 바뀐다.

취소 버튼 스타일

버튼 텍스트가 좀 굵게 보인다. 애플의 취소 버튼 가이드라인대로 스타일을 표시해 주는 것 같다. 물론 이 스타일만 빼면 기본 예제와 사실상 동일하다.

무서운(?) 버튼

버튼의 역할(role) 중에는 .destructive라는 무서운(?) 이름이 있다.

.alert("Alert Title", isPresented: $showingAlert) {
    Button("Destruct", role: .destructive) {}
} message: {
    Text("This is alert dialog sample")
}

위와 같은 형태로 코딩할 경우 아래와 같이 경고창 스타일이 바뀐다.

자동으로 나타난 취소 버튼과 무서운 버튼

웬일인지 버튼이 두 개가 표시된다. 하나는 직접 코딩한 무서운(?) 버튼이고 다른 하나는 코딩하지 않았음에도 자동으로 나타나는 취소(Cancel) 버튼이다. 여기서 .destructive 역할(role)로 구현한 버튼은 굉장히 위험하거나 치명적인 혹은 되돌리기가 힘든 일을 함을 명시적으로 표현하기 위해 시뻘건(?) 색으로 나타난다. 그리고 당연히 이런 기능의 경우 취소 버튼을 반드시 제공해야 한다. 그래서 취소 버튼이 자동으로 나타나는 것 같다. 아마도 이런 취소 버튼 요구도 애플의 UI 및 UX 가이드라인에 있는 내용 같다.

당연하게도 여기서 .destructive 역할의 버튼이 눌리면 코딩된 내용이 실행될 테고, 자동으로 표시되는 취소(Cancel) 버튼은 눌리면 당연히 아무것도 호출되지 않고 경고창이 닫히는 것으로 끝난다.

참고로 별도로 .cancel role을 지정한 버튼을 추가 구현하면 자동으로 나타났던 취소(Cancel) 버튼 대신 직접 코딩한 버튼이 나타난다. 취소 동작을 별도로 구현해야 한다면 .cancel role의 버튼도 추가해주면 된다는 이야기다.

반응형

더 많은 버튼

경고창의 버튼 개수는 제약이 보이지 않는다. 아래처럼 3개의 버튼을 연달아 붙이는 것도 가능하다.

.alert("Alert Title", isPresented: $showingAlert) {
    Button("Hmm") {}
    Button("What?") {}
    Button("Failed", role: .destructive) {}
} message: {
    Text("This is alert dialog sample")
}

버튼이 3개 이상인 경우 세로로 배치된다. 그리고 .destructive role로 정의된 버튼이 있으면 어김없이 취소(Cancel) 버튼이 함께 표시된다.

경고창의 버튼 갯수가 많으면 세로로 배치된다

당연히 .cancel 역할(role)의 버튼을 별로도 추가하면 기본 취소(Cancel) 버튼 대신 코딩한 버튼이 나타난다는 점은 동일하다.

데이터 싣기

필요하다면 이전 방식처럼 데이터를 실어주는 방법도 여전히 쓸 수 있다. 대충 아래와 같은 식이다.

enum AlertType {
    case warn, error
}

struct ContentView: View {
    @State private var showingAlert = false
    @State private var alertType = AlertType.warn
    
    var body: some View {
        VStack {
            Button("Show Warning Alert") {
                alertType = .warn
                showingAlert = true
            }
            .padding()
            Button("Show Error Alert") {
                alertType = .error
                showingAlert = true
            }
            .padding()
        }
        .alert("Alert Title", isPresented: $showingAlert, presenting: alertType, actions: { type in
            if type == .warn {
                Button("Warning!") {}
            } else {
                Button("Error!") {}
            }
        }, message: { type in
            if type == .warn {
                Text("This is warning dialog")
            } else {
                Text("This is error dialog")
            }
        })
    }
}

뭔가 복잡한 것 같지만 결국 경고 타입을 설정해주기 위한 타입과 프로퍼티를 추가했고 이걸 이용해 경고창을 약간은 다이내믹하게 뛰우는 코드다.

솔직히 말해서 여전히 좀 귀찮은 것 같다. 역시 경고창은 이전 UIKit이나 AppKit 스타일이 확실히 편한데 말이다.

관련된 글

 

SwiftUI에서 경고 팝업(Alert) 표시하기

SwiftUI에서는 경고 팝업(Alert Dialog)을 띄우는 방법이 좀 생소하다. 솔직히 말해서 좀 귀찮다. 어쨌든 방법을 찾았기에 글로 살짝 풀어서 정리해본다. 참고로 순수 SwiftUI 코드만 쓰기 때문에 모양은

seorenn.tistory.com

728x90
반응형

댓글