1. 왜 SwiftUI의 Alert이 아닌 UIKit의 Alert을 사용하는가?

SwiftUI의 Alert

먼저 SwiftUI에서 제공되는 Alert을 사용하기 위한 필요한 요소에 대해 알아보자.

1. alert이 열려있는지 닫혀있는지에 대한 정보를 담은 Bool 타입의 State 변수를 선언한다.

2. View에 alert을 체이닝 형식으로 선언한 후 아까 선언한 State 변수를 연결한다.

3. View의 alert 클로저에 Action처리를 포함한 Alert(View)을 추가한다.

struct AView: View {
	// 1
    @State var isShowingAlert = false
    
	var body: some View {
    	VStack {
        	Button(action: { 
            	isShowingAlert = true
            }) {
            	Text("show alert")
            }
        }
        .alert(isPresented: $viewModel.showingPayAlert) { 	// 2
            // 3
            Alert(
                    title: Text("알림"),
                    message: Text("수락하시겠습니까?"),
                    primaryButton: .default(Text("확인")) {
                        print("action!")
                    },
                    secondaryButton: .cancel(Text("취소")
            )
        }
    }
}

 SwiftUI에서 제공되는 Alert을 사용하려면 해당 Alert이 열림과 닫힘을 알 수있는 State 변수 하나, View타입 끝에 체이닝 형식으로 alert을 하나하나 달아줘야 한다. 만약 여러개의 화면에 모두 각각 alert이 필요하면 매번 State 변수를 만들고 매번 alert을 달아준 다음 해당 action을 추가해야한다. 물론 최상단의 View에 하나의 alert을 달아놓고 매번 최상단의 alert의 binding 변수를 변경해주거나 하는 방법으로 해결할 수 있지만 최상단의 State값이 변경됨으로써 생기는 사이드이펙트들을 또한 신경써줘야 하는 단점이 있었다. 또한 하나의 View에 여러개의 alert이 필요한 경우 하나의 View 타입에 여러개의 alert을 달아주는 경우 정상적으로 동작하지 않는 경우가 생겨 불필요한 코드들이 추가되기도 한다.

 물론 선언형인 SwiftUI에서 어울리는 방법이긴 하다. 하지만 개인적으로 모든 View에서 매번 저 3가지의 작업을 한다는게 번거롭고 코드의 양도 쓸데없이 커진다는 느낌을 받았다.

 

SwiftUI에서 UIKit

특정 Action을 처리하는 alert인데 굳이 명령형으로 하지 않고 선언형을 사용 할 필요가 있을까?

아래 코드처럼 UIKit를 사용한 AlertController를 만들어 단지 호출만 하여 간단 명료하게 Alert을 표시할 수 있다.

struct BView: View {
	var body: some View {
    	Button(action: { 
        	AlertController.showAlert(
       			title: "알림",
			message: "승인하시겠습니까?",
              	  	primaryAction: { print("승인") }
            )
        }) {
        	Text("show alert!")
        }
    }
}

아래 코드는 가장 상위의 ViewController를 찾은 후 해당 ViewController에 Alert을 추가하는 코드이다.

UIKit의 UIAlertController를 현재 Scene의 가장 상위의 ViewController를 가져와 추가하는 작업이다.

import Foundation
import UIKit

final class AlertController {
    static func showAlert(
        title: String = "알림",
        message: String?,
        primaryAction: @escaping () -> ()
    ) {
        let alert = UIAlertController(
            title: title,
            message: message,
            preferredStyle: .alert
        )
        alert.addAction(
            .init(
                title: "확인",
                style: .default,
                handler: { _ in
                    primaryAction()
                }
            )
        )
        alert.addAction(
            .init(
                title: "취소",
                style: .cancel
            )
        )
        rootController().present(alert, animated: true)
    }
    
    private static func rootController() -> UIViewController {
        guard let screen = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
            return .init()
        }
        
        guard let root = screen.windows.first?.rootViewController else {
            return .init()
        }
        
        return root
    }
}

 

 

고찰

SwiftUI를 사용하다 보면 참 편한기능이 많고 생산성이 엄청 좋고 유지보수, 코드 관리가 편하다는 것을 느낀다. 하지만 무조건 장점만은 있는게 아니기 때문에 UIKit의 장점과 SwiftUI의 장점을 잘 종합적으로 사용해야 한다는 생각이 든다.

 

 

반응형

+ Recent posts