ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift WKWebView 양방향 통신
    iOS/개념정리 2024. 6. 11. 15:31

    apple에서 제공해주는 WKWebView라는 WebView가 있습니다.

    원하는 url를 load 할 수 있고, 아니면 직접 html String을 load할 수 있습니다.

    SFSafriViewController라는 것을 사용해서 만들 수 있지만 WKWebView가 좀 더 Custom하기 용이하다구 생각합니다.

    iOS 8.0 부터 생겼고, WebKit을 import해서 사용하면 됩니다.

    프로젝트에 들어가면 온전한 native소스가 아닌 webView와 같이 사용하는경우가 많습니다.
    거기서 참고할 만한 간단하게 WebView -> Native랑 Native -> WebView를 알아보겠습니다.

    우선 htmlString을 사용하여 간단하게 웹뷰를 구성하고 그 구성한것들을 이용하여 통신 해보겠습니다.

     

    화면 구성

     

    다음과 같이 WKWebView를 만들어 줍니다.

     

    lazy var webView: WKWebView = {

            let controller = WKUserContentController()

            //htmlString에서 webkitMessage handler 등록된 이벤트를 사용하여 발생시 UserContentController로 들어옴.

            controller.add(self, name: "btnClick")

            

            let config = WKWebViewConfiguration()

            config.userContentController = controller

            

            let tempWebView = WKWebView(frame: .zero, configuration: config)

            tempWebView.uiDelegate = self

            tempWebView.navigationDelegate = self

            

            tempWebView.loadHTMLString(htmlString, baseURL: nil)

            

            return tempWebView

        }()

     

    다음 네이티브의 버튼을 만들어 줍니다.

     

    lazy var sendToWebViewButton: UIButton = {

            let tempBtn  = UIButton()

            

            tempBtn.setTitle("send to webView", for: .normal)

            tempBtn.backgroundColor = .red

            tempBtn.addTarget(self, action: #selector(sendToWebViewAction), for: .touchUpInside)

            tempBtn.frame = CGRect(x: (UIScreen.main.bounds.width / 2) - 90, y: (UIScreen.main.bounds.height / 2) - 25, width: 180, height: 50)

            tempBtn.layer.cornerRadius = 10

            

            return tempBtn

        }()

     

    다음 load할 html String을 만들어 줍니다.

     

    fileprivate let htmlString = """

            <!DOCTYPE html>

            <meta content="width=device-width,user- scalable=no" name="viewport">

            <html>

                <body>

                    <p> WebView </p>

                    <button onclick="sendScriptMessage()">

                        native로 보내기!

                    </button>

                    <div id="recieveAction">Hello World</div>

        

                    <script>

                        function sendScriptMessage() {

                            window.webkit.messageHandlers.btnClick.postMessage('안녕')

                        }

                        function recieveActionFromNative(){

                            const content = document.getElementById('recieveAction')

                            content.innerHTML = '<span style = "color: red;"> recieveAction </span>'

                        }

                    </script>

                </body>

            </html>

        """

     

    그리고 viewdidLoad에 만들어둔 위의 것들을 화면에 표시 해 줍니다.

     

    override func viewDidLoad() {

            super.viewDidLoad()

            

            self.view.addSubview(webView)

            webView.translatesAutoresizingMaskIntoConstraints = false

            view.addConstraints([

                webView.topAnchor.constraint(equalTo: view.topAnchor),

                webView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

                webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),

                webView.trailingAnchor.constraint(equalTo: view.trailingAnchor)

            ])

            

            webView.addSubview(sendToWebViewButton)

        }

     

     

    UI 구성

    그러면 위와 같이 화면이 만들어 집니다.

    빨간 버튼은은 Native 버튼이고 나머지는 상단의 부분은 WebView입니다.

     

     

     WkWebView -> Native

     

    위에서 보면 WkWebView를 구성할때 WKUserContentController에 add하여 이벤트를 등록해 줬습니다.

    이렇게 등록된 이벤트는 WebKit에 Message Handler를 통해서 

     

     // Web -> Native로 들어오는 지점

        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

            print("message: \(message.name)")        

        }

     

    위 함수를 통해 들어옵니다. 그래서 저 버튼을 누르면 "message: btnClick" 이런 메세지가 로그에 찍힙니다.

     

    Native -> WkWebView



    이제 네이티브에서 WKWebView를 건드려 볼겁니다.

    위에서 네이티브 버튼을 만들때 등록한 타겟을 보면

    위처럼 sendToWebViewAction이 있습니다 이 함수를 만들어 볼겁니다.

     

    // Native -> Web (javascript에 recieveACtionFromNative() 실행)

        @objc func sendToWebViewAction(){

            webView.evaluateJavaScript("window.recieveActionFromNative()")

        }

    이런식으로 하면 webView에 load되어있는 recieveActionFromNative 이게 실행되어서 글자가 빨간색으로 변하면서 글자 내용이

    recieveAction 이렇게 변하게 될겁니다.

     

    감사합니다.

     

    'iOS > 개념정리' 카테고리의 다른 글

    [iOS] Alamofire + Combine with Clean Architecture  (0) 2024.01.29
    <Swift>Combine(2) 사용하기  (0) 2023.03.15
    <Swift> Combine(1) 사용하기  (0) 2023.03.03
    <Swift>Skeleton 사용하기  (0) 2022.10.31
    <Swift> Kingfisher 사용하기  (0) 2022.10.14

    댓글

Designed by Tistory.