본문 바로가기

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

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

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

macOS에서 본 경고 팝업의 모습

경고 팝업을 띄우기 위해서는 Alert 구조체를 이용한다. 아래는 Alert 인스턴스를 생성하는 예제다.

Alert(title: Text("Alert"), 
      message: Text("Alert Dialog"), 
      dismissButton: .default(Text("Close")))

상상대로라면 이 코드를 특정 View의 body에 넣으면 될 것 같다. 그런데 그게 잘 안 된다. 아래와 같은 오류가 나면서 말이다.

Return type of property 'body' requires that 'Alert' conform to 'View'

그러니까 Alert는 View가 아니라는 말로 해석된다. 까다로운 녀석이다.

그렇다며 어떻게 써야 할까?

대부분의 뷰(View)들 - 예를 들어 VStack이나 HStack 같은 레이아웃이나 컨테이너 뷰 종류 - 에서는 .alert 함수가 제공된다. 여기서 Alert 인스턴스를 리턴할 수 있다.

이 방법을 쓰기 위해서는 약간의 준비가 더 필요하다. 뷰 구조체에 Alert 다이얼로그를 위한 스테이트(State) 프로퍼티를 하나 선언하자.

@State private var showingAlert = false

그리고 이걸 바인딩해서 .alert 호출 코드를 구현한다.

.alert(isPresented: $showingAlert) {
    Alert(title: Text("Alert"), 
          message: Text("Alert Dialog"), 
          dismissButton: .default(Text("Close")))
}

이제 showingAlert 프로퍼티가 true가 되면 경고 팝업을 볼 수 있다. 반대로 끄려면 false를 지정하면 되겠지만 dismissButton이 자동으로 바꾸기 때문에 신경 쓸 필요는 없다.

아래는 버튼을 이용해 경고 팝업을 띄우는 전체 코드다.

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

    var body: some View {
        VStack {
            Button("Show Alert") {
                showingAlert = true
            }
        }
        .padding()
        .alert(isPresented: $showingAlert) {
            Alert(title: Text("Alert"), 
                  message: Text("Alert Dialog"), 
                  dismissButton: .default(Text("Close")))
        }
    }
}

아래 스샷들은 위 코드를 멀티플랫폼 앱 프로젝트에서 돌려본 결과다.

버튼을 누르기 전
버튼을 눌러서 경고 팝업이 뜬 상태

왜 귀찮은 방법인지 이해할 수 있을 것이다. 특정 스테이트 하나를 엮어서 이 프로퍼티를 이용해 경고 팝업을 띄워야 하는데 준비가 좀 많다. 거기다 예제는 달랑 하나뿐이지만 만약 두 개 이상의 경고 메시지가 필요하다면 더 귀찮은 일이 벌어질 수 있다.

좀 더 쉽고 단순하고 명쾌한 방법이 있었으면 좋겠다.

그나저나 내 시뮬레이터의 경고 팝업은 왜 노란색 배경으로 뜨는 것일까? 🤔

관련된 글

 

iOS 시뮬레이터의 이상한 노란색(?) 문제

Xcode 4.3을 설치한 이후 무슨 일이 있었는지는 모르겠는데 Title Bar나 Alert Popup 등의 배경색이 노랗게 보이는 문제가 발생하기 시작했다. 아래 스샷이 그 증거(?)다. 전부 문제가 있는 것도 아니고

seorenn.tistory.com

728x90
반응형

댓글