본문 바로가기

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가 아니라는 말로 해석된다. 까다로운 녀석이다.

728x90

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

대부분의 뷰(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
반응형

댓글