[iOS] WKWebView (2) - 웹 뷰 사용하기

2021. 5. 25. 02:08iOS

반응형

이전 글에서 WKWebView (1) 사용하기에 대해 작성했었는데요~

 

[iOS] WKWebView (1) - 웹 뷰 사용하기

이번에 프로젝트를 진행하면서 이번에 웹 뷰를 사용해서 해야하는 간단한 작업을 받았습니다 :) 그래서 이 참에 WKWebView는 자주 사용하는 컴포넌트이기도 해서 확실하게 공부해놓으면 도움이 되

dongminyoon.tistory.com

이번에는 이어서 WebView에서 JavaScript 코드를 어떻게 호출하고 JavaScript에서 어떻게 네이티브 앱 코드를 호출하는지 어떻게 JavaScript로부터 이벤트를 받아서 실행하는지에 대해 알아보겠습니다.

 

WKUserContentController - 웹, 네이티브 소통하기

우선 JavaScript 코드를 네이티브에서 호출하거나 네이티브 코드를 JavaScript에서 호출하는 방법을 알기 위해서는 이 객체에 대해서 알아야 합니다. 먼저, Apple 문서의 설명을 보면 이 객체를 다음과 같이 설명하고 있습니다.

JavaScript 코드와 네이티브 웹 뷰 사이의 상호작용을 관리하고 네이티브 웹 뷰에서 콘텐츠를 필터링하기 위한 개체라고 합니다.

즉, Apple 개발자 문서만 봐도 WKUserContentController는 사이에서 중재 역할을 하고 있습니다. 이 객체를 사용하면 할 수 있는 것들을 다음과 같은 것들이 있따고 합니다.

  • JavaScript 코드를 웹 페이지에 주입하는 것
  • JavaScript 코드를 네이티브 웹 뷰에서 호출하는 것
  • 필터를 등록해서 특정 컨텐츠를 띄우는 것을 막는 것

이런 것들이 WKUserContentController를 이용해서 가능하다고 합니다.

 

그렇다면 WKUserContentController를 사용해서 어떻게 이러한 동작들을 하는지 알아볼게요...!!

 

먼저, WKUserContentController는 이전 포스팅에서 알아본 WKWebViewConfigurationuserContentController 프로퍼티에 주입하여 사용할 수 있는 객체입니다.

let configuration = WKWebViewConfiguration()
let contentController = WKUserContentController()

configuration.userContentController = contentController

let webView = WKWebView(frame: .zero, configuration: configuration)

이렇게 사용해서 WKUserContentControllerWKWebView에 할당하는 것이 가능합니다.

그렇다면 이제 JavaScript 코드를 네이티브에서 호출하는 방법과 JavaScript에서 네이티브 코드를 호출하는 방법에 대해 알아볼게요 :)

 

먼저 JavaScript 코드를 네이티브에서 호출하는 방법입니다. 크게 2가지가 있는 것으로 공부했는데요.

 

우선, 첫번째는 JavaScript 소스를 처음 WebView를 로드해 올 시점에 할당하는 방법입니다.

let configuration = WKWebViewConfiguration()
let contentController = WKUserContentController()

let userScript = WKUserScript(source: "javascript source", injectionTime: .atDocumentEnd, forMainFrameOnly: false)
contentController.addUserScript(userScript)

configuration.userContentController = contentController

let webView = WKWebView(frame: .zero, configuration: configuration)

let url = URL(string: "https://www.apple.com")
let request = URLRequest(url: url!)
webView.load(request)

이렇게 load하기 이전 시점에 WKContentControllerWKUserScript를 주입하는 방법입니다.

 

두번째는 evaluateJavaScript(_:completionHandler:) 메소드를 이용하는 방법입니다.

지금 이 메소드를 호출하게 되면, WebView에서 직접적으로 JavaScript 코드를 호출합니다. completionHandler에서는 JavaScript 코드가 성공했으면 결과를 받아서 콜백함수로 실행할 수 있고 실패했으면 Error 값을 받아서 처리할 수 있습니다.

let webView = WKWebView(frame: .zero)

let javaScriptSource = "if (true) { print("Call JavaScript Function") }"

webView.evaluateJavaScript(javaScriptString) { object, error in
    print(object)
    print(error)
} 

다음과 같이 호출하면 JavaScript 코드를 직접적으로 네이티브에서 호출할 수 있습니다.

 

지금까지는 JavaScript 코드를 네이티브에서 호출하는 방법이였습니다..!!

그렇다면 지금부터는 JavaScript에서 네이티브에 메세지를 전달하는 방법을 알아볼게요 :)

 

우선, WKScriptMessageHandler라는 프로토콜을 채택해서 사용해야합니다.

그리고 WKUserContentController에 저희가 JavaScript로부터 받아서 사용할 메세지의 이름을 등록해주어야 해당 메세지가 날라왔을 때, 제대로 전달해서 사용할 수 있습니다.

class SomeWebView: WKWebView {
    func setupContentController() {
        let contentController = self.configuration.userContentController
        contentController.add(self, name: "MessageName")
    }
}

extension SomeWebView: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        // JavaScript에서 메세지를 보낼 때, 보내는 message 이름
        let messageName = message.name
        
        // JavaScript에서 메세지를 보낼 때, 같이 보내는 Parameter Any 타입
        let body = message.body
    }
}

이렇게 네이티브에서 JavaScript의 호출을 받아서 메소드를 처리하는 것이 가능합니다.

 

지금까지 JavaScript에서 네이티브의 코드를 호출하는 방법, 네이티브에서 JavaScript의 코드를 호출하는 방법을 알아보았습니다 :)

 

다음은 Alert 액션을 받아서 네이티브에서 처리하는 방법을 알아볼게요!

여기는 훨씬 간단합니다...!! 저도 사용한 적은 없지만 공부하는 김에 같이 알아보았어요 

 

WKUIDelegate - Alert 액션 네이티브에서 처리하기

WKUIDelegate를 이용하면 웹에서 표현되는 새로운 창을 열 때와 같은 이벤트를 받아서 네이티브 앱에서 띄워주는 동작들이 가능하게 됩니다. 기존에 Alert를 띄워주는 것이 WebView 내에서 웹의 요소로 띄워주는 것이었다면 네이티브 앱에서 이 이벤트를 가로채서 UIAlertViewController 등으로 대체해서 띄워주는 것이 가능하게 됩니다..!!

 

여기서는 간단하게 두 가지의 메소드를 살펴보겠습니다~~!! (다른 window들을 받아서 표현하는 것도 있어요..!!)

 

첫번째는 webView(_:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:) 입니다.

이 메소드는 JavaScript에서 Alert 메세지를 받았을 때, 호출되는 메소드에요..!!

 

두번째는 webView(_:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:) 입니다.

이 메소드는 Cancel, OK에 관한 이벤트에 대한 핸들링이 가능하게 됩니다. 

마지막 completionHandler에 Bool 값을 넣어서 실행함에 따라 핸들링이 가능하게 됩니다.

class SomeWebView: WKWebView {
    func setupWebView() {
        self.uiDelegate = self
    }
}

extension SomeWebView: WKUIDelegate {
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        let confirmAction = UIAlertAction(title: "CC_COMMON_CONFIRM".localized, style: .default) { _ in
            completionHandler()
        }
        alertController.addAction(confirmAction)
    }
    
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "COMMON_CONFIRM_CANCLE".localized, style: .cancel) { _ in
            completionHandler(false)
        }

        let confirmAction = UIAlertAction(title: "CC_COMMON_CONFIRM".localized, style: .default) { _ in
            completionHandler(true)
        }
        alertController.addAction(cancelAction)
	alertController.addAction(confirmAction)
    }
}

이렇게해서 웹으로부터 window를 띄우는 액션들을 받아서 네이티브에서 처리하는 것이 가능합니다...!!

 

오늘은 이렇게 WKWebView (2)번째 시리즈에 대해 작성해보았습니다~ :)

도움이 되었으면 좋겠습니다.

혹시 잘못된 점이나 더 알고싶은 점이 있으면 알려주세요...!!

 

 

반응형