웹킷의 웹뷰에서 window.webkit.messageHandlers를 이용하면 네이티브 영역(Swift 코드 부분)으로 메세지를 전달할 수 있다.

 

WKUserContentController 를 이용해서 메세지의 이름과 메세지가 전달될 때의 처리할 대상(self)를 등록해야 한다. 다음과 같이 작성하면 될 줄 알았다.....

let contentController = WKUserContentController()
contentController.add(self, name: "hello")
webView.configuration.userContentController = contentController

웹뷰에서 webkit.messageHandlers를 통해서 보내는 메세지는 다음과 같이 작성한 메소드에 메세지 이름과 메세지의 바디 부분을 얻을 수 있다.

extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "hello", let messageBody = message.body as? String {
            print("Hello Message body :", messageBody)
        }
    }
}

다음은 웹뷰에서 webkit.messageHandlers로 메세지를 전달하는 코드다.

window.webkit.messageHandlers.hello.postMessage('Hello WebKit');

코드는 상당히 간단한 편인데 생각대로 동작하지 않았다.

원인을 찾다보니 웹뷰에서 webkit의 값이 undefined이고 그래서 메세지 전달이 안되고 있었다. 다음 그림은 사파리로 웹뷰 콘솔을 확인하는 모습이다. (사파리 -> 개발자용 -> 시뮬레이터 -> Document)

문제가 된 부분은 다음 코드였다.

let contentController = WKUserContentController()
contentController.add(self, name: "hello")
webView.configuration.userContentController = contentController

웹뷰의 configuration.userContentController 와 contentController가 서로 다른 객체였기 때문에 메세지와 메세지 핸들러가 등록되지 않았다. 대충 이러면 되겠지~ 하는 생각으로 코드를 짜다가 몇 시간이나 날린건지..

 

웹뷰의 configuration 객체에는 userContentController가 기본 생성되어 있기 때문에 다음과 같이 작성하면 된다.

let contentController = webView.configuration.userContentController
contentController.add(self, name: "hello")

 

반응형

+ Recent posts