SwiftUI: WKWebView의 UIRepresentableView에서 웹 페이지의 Alert, Confirm, Prompt 표시
관련 글
소개
UIDelegate에서 구현해야되는 자바스크립트 경고창 (Alert, Confirm, Prompt) 표시는 어떻게 해야 할까요?
- Coordinator 클래스를 만들고
WKUIDelegate를 준수(conform)- 부모 뷰 (
WebViewRP)를 참조하는 변수를 정의하고 이 변수를 통해 코디네이터와 통신
- 부모 뷰 (
- 코디네이터 클래스 안에 자바스크립트 경고창 표시와 관련된 함수를 오버라이딩 및 정의
- 제목 메시지 및 Alert 표시 여부는
@State,@Binding변수들을 통해 전달- 참고)
@State및@Binding변수들은ObservableObject뷰모델의@Published로 대체할 수 있습니다.
- 참고)
- Alert의 확인버튼, Confirm의 예/아니오 버튼, Prompt의 텍스트 필드 및 전송/취소 버튼이 클릭되었을 때 해야 할 작업등은
(파라미터) -> Void형태의 클로저 함수로 전달- 참고)
ObservableObject뷰모델을 사용하는 경우 뷰모델에 해당 클로저 함수를 저장하도록 지정할 수 있습니다.
- 참고)
ObservableObject를 사용하여 분리한 코드는 여기에서 볼 수 있습니다.
코드 (@State, @Binding 사용)
https://gist.github.com/ayaysir/99b48bf69a42de3e4ae79d44e229a7f1
CompletionHandler를 사용하는 메서드에서 completionHandler의 역할
웹 페이지의 자바스크립트 실행 부분에서 경고창이 뜨면 다음 명령을 기다리게 됩니다. iOS 앱에서 Handler 함수가 실행되면 다음에 해야 할 자바스크립트 작업을 이어서 실행합니다.
이 핸들러 함수를 컨텐트 뷰에 전달하고 SwiftUI의 경고창에서 버튼을 눌렀을 때 전달받은 핸들러를 실행하면 웹페이지의 자바스크립트가 다음 작업을 실행하게 되는 것입니다.
async/await 메서드에서 self.parent.alertHandler = {…} 부분의 동작 원리
핵심 개념
_alertHandler_는 @Binding으로 전달된 클로저입니다. Swift의 클로저는 코드 블록을 캡처하고, 나중에 실행될 수 있는 “일급 객체”입니다. 이 클로저를 continuation.resume()로 연결하여, JavaScript alert()가 비동기적으로 처리될 수 있도록 합니다.
동작 원리
- alertHandler 초기 설정
parent.alertHandler는 UIViewRepresentable의 SwiftUI View와 연결된 상태 변수입니다.- 초기값은 비어 있지만,
webView(_:runJavaScriptAlertPanelWithMessage:initiatedByFrame:)호출 시 새로운 클로저를 할당합니다.
- withCheckedContinuation 사용
- Swift Concurrency에서
withCheckedContinuation은 콜백 기반 코드를async/await로 변환하는 데 사용됩니다. - JavaScript
alert()이벤트는 비동기로 처리되므로, Continuation을 사용해 비동기 흐름을 제어합니다.
- Swift Concurrency에서
-
클로저 저장
- JavaScript
alert()호출 시self.parent.alertHandler에 다음 동작을 정의한 클로저를 할당합니다:
1 2 3
self.parent.alertHandler = { continuation.resume() }- 이 클로저는 SwiftUI의 Alert의 “OK” 버튼과 연결되어, 버튼이 눌릴 때 실행됩니다.
- JavaScript
- Alert 표시
showAlert를true로 설정하면 SwiftUI에서 Alert이 표시됩니다.- Alert의 “OK” 버튼을 누르면
alertHandler()가 실행되고, Continuation이 재개됩니다.
- Continuation 재개
continuation.resume()가 호출되면,await가 완료되고webView(_:runJavaScriptAlertPanelWithMessage:)의 호출이 끝납니다.- 이로써 비동기 흐름이 정상적으로 처리됩니다.
This post is licensed under
CC BY 4.0
by the author.