이전 글에서 이어집니다.
웹킷뷰(WKWebView) 에서 자바스크립트를 실행하려면 자바스크립트 모드가 활성화되어야 합니다. 다음 코드를 뷰 컨트롤러에 추가합니다. iOS 14 버전과 이전 방식에 차이가 있습니다.
먼저 딜리게이트를 구현하는 뷰 컨트롤러의 extension
을 추가합니다.
extension ViewController: WKUIDelegate, WKNavigationDelegate { }
다음 웹킷뷰를 초기화하는 함수를 작성합니다. 하이라이트 부분이 자바스크립트를 활성화시키는 부분입니다.
func loadHelpPage() { // 웹 파일 로딩 webView.uiDelegate = self webView.navigationDelegate = self let pageName = "index" guard let url = Bundle.main.url(forResource: pageName, withExtension: "html", subdirectory: "webpage") else { return } webView.loadFileURL(url, allowingReadAccessTo: url) if #available(iOS 14.0, *) { webView.configuration.defaultWebpagePreferences.allowsContentJavaScript = true } else { // Fallback on earlier versions webView.configuration.preferences.javaScriptEnabled = true } }
다음 HTML 파일에 자바스크립트를 작성합니다.
<body> <h1 id="title">안녕하세요</h1> <img src="image.png" width="100%"> <a href="https://google.com">하이퍼링크</a> <button id="btn-alert">자바스크립트</button> <script> document.getElementById("title").textContent = "Javascript" </script> </body>
이렇게 하면 원래 제목은 안녕하세요
이지만 자바스크립트가 실행되면서 Javascript
로 변하는 것을 알 수 있습니다.
하지만 일반 웹브라우저에서는 당연하게 되던 것들이 여기서는 작동하지 않는 경우가 많습니다. 그 중에는 alert, confirm 등의 경고창을 뜨게 하는 명령이 실행되지 않는 것 등이 있습니다.
이러한 alert
등의 자바스크립트 코드가 작성되었을 때 해야할 동작은 네이티브 앱에서 수동으로 구현해야 합니다.
먼저 alert
을 구현하는 방법에 대해 알아보겠습니다.
위의 extension
안에 아래 코드를 작성합니다. (runJavaScriptAlertPanelWithMessage
)
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert) let alertAction = UIAlertAction(title: "확인", style: .default, handler: {_ in completionHandler() }) alert.addAction(alertAction) DispatchQueue.main.async { self.present(alert, animated: true, completion: nil) } }
여기서 message
, completeHandler
변수를 사용해서 얼럿 띄우는 것을 구현해야 합니다. message
는 자바스크립트의 alert("...")
에 작성된 메시지이고, completeHandler
는 작업을 완료하는 콜백 함수입니다. 이 변수들을 사용해 일반적인 iOS의 얼럿 형태로 코드를 작성했습니다.
그리고 자바스크립트 부분에 다음 코드를 작성하면 얼럿창이 뜨는 것을 확인할 수 있습니다.
alert("얼럿이 왜 안돼?")
자바스크립트의 경고창으로는 alert
외에 confirm
(확인/취소), prompt
(필드에 값을 입력)이 있습니다. 이것들도 위의 방법으로 구현해보도록 하겠습니다.
confirm (runJavaScriptConfirmPanelWithMessage
)
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { let alert = UIAlertController(title: "Confirm", message: message, preferredStyle: .alert) let noAction = UIAlertAction(title: "아니오", style: .default) { _ in completionHandler(false) } let yesAction = UIAlertAction(title: "예", style: .default) { _ in completionHandler(true) } alert.addAction(noAction) alert.addAction(yesAction) DispatchQueue.main.async { self.present(alert, animated: true, completion: nil) } }
앞의 alert
과의 차이점은 completionHandler
의 파라미터에 Bool
값이 들어가서 true
/false
로 예/아니오를 구현하는 데에 있습니다.
자바스크립트를 작성합니다.
let isConfirm = confirm("승낙하시겠습니까?") if(isConfirm) { document.getElementById("title").textContent = "Confirm YES" }
아니오
버튼을 누르면 아무 변화가 없고, 예
버튼을 누르면 위와 같이 제목이 바뀌는 것을 볼 수 있습니다.
prompt (runJavaScriptTextInputPanelWithPrompt
)
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { let alert = UIAlertController(title: "Prompt", message: "메시지를 입력하세요.", preferredStyle: .alert) alert.addTextField { textField in textField.placeholder = defaultText } let okAction = UIAlertAction(title: "OK", style: .default) { _ in if let text = alert.textFields?[0].text { completionHandler(text != "" ? text : defaultText) } else { completionHandler(defaultText) } } alert.addAction(okAction) DispatchQueue.main.async { self.present(alert, animated: true, completion: nil) } }
text
또는 defaultText
에서 메시지를 받으면, 메시지를 원문 또는 가공하여 completHandlert(text)
으로 보내면 자바스크립트가 네이티브 앱으로부터 메시지를 받는 형식입니다.
자바스크립트를 작성합니다.
const promptStr = prompt("prompt", "기본값") document.getElementById("title").textContent = promptStr
위와 같이 입력값에 따라 제목이 바뀌는 것을 볼 수 있습니다.
0개의 댓글