이전 글에서 이어집니다.

 

웹킷뷰(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

위와 같이 입력값에 따라 제목이 바뀌는 것을 볼 수 있습니다.

문의 | 코멘트 또는 yoonbumtae@gmail.com


카테고리: Swift


0개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다