개발

RxSwift로 웹뷰 브릿지 로직 만들기

한번사는인생~키야 2024. 7. 9. 13:03
728x90

RxSwift를 사용한 웹뷰 브릿지 로직 구현

RxSwift를 사용하여 웹뷰와 앱 간의 통신을 위한 브릿지 로직을 간편하고 효율적으로 구현할 수 있습니다.

1. 요구 사항 정의

  • 웹뷰에서 JavaScript 함수를 호출하여 앱 내 함수 실행
  • 앱 내 함수 실행 결과를 웹뷰에 전달
  • 웹뷰에서 발생하는 이벤트를 앱 내에서 처리

2. WKScriptMessage 및 WKUserContentController 설정

  • WKUserContentController인스턴스를 생성하고 웹뷰에 설정합니다.
  • WKScriptMessage객체를 사용하여 JavaScript 함수 이름과 전달할 데이터를 정의합니다.
  • WKUserContentController에 scriptMessageHandler를 설정하여 JavaScript 함수 호출을 처리합니다.
import UIKit

import RxSwift

import WebKit



class WebViewController: UIViewController {



    @IBOutlet weak var webView: WKWebView!



    private let disposeBag = DisposeBag()



    override func viewDidLoad() {

        super.viewDidLoad()



        setupWebView()

    }



    private func setupWebView() {

        let userContentController = WKUserContentController()

        userContentController.add(self as WKScriptMessageHandler, name: "appFunction") // JavaScript 함수 이름

        webView.configuration.userContentController = userContentController



        let url = URL(string: "https://www.example.com")!

        webView.load(URLRequest(url: url))

    }

}



extension WebViewController: WKScriptMessageHandler {



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

        if message.name == "appFunction" { // JavaScript 함수 이름 확인

            guard let data = message.body as? String else { return }

            // data를 통해 JavaScript 함수에서 전달된 데이터 처리

            DispatchQueue.main.async {

                // 앱 내 함수 실행 및 결과 처리

                let result = self.callAppFunction(data: data) // 앱 내 함수 호출

                // 결과를 웹뷰에 전달

                self.webView.evaluateJavaScript("window.receiveResult('\(result)')")

            }

        }

    }



    // 앱 내 함수 정의

    private func callAppFunction(data: String) -> String {

        // data를 통해 전달된 데이터를 활용하여 앱 내 로직 수행

        // ...



        // 결과를 문자열로 반환

        return "앱 함수 실행 결과"

    }

}

 

3. RxSwift를 사용한 브릿지 로직 구현

  • RxSwift의 Observable을 사용하여 JavaScript 함수 호출 이벤트를 감지하고 처리합니다.
  • Subject를 사용하여 앱 내 함수 실행 결과를 웹뷰에 전달합니다.
extension WebViewController {



    // JavaScript 함수 호출 이벤트 감지

    var appFunctionCall: Observable<String> {

        Observable.create { observer in

            webView.addObserver(self, forKeyPath: "userContentController.scriptMessageHandler", options: .new, context: nil)

            return Disposables.create {

                webView.removeObserver(self, forKeyPath: "userContentController.scriptMessageHandler")

            }

        }

        .map { $0.newValue as! WKScriptMessageHandler }

        .map { $0 as? WebViewController } // 타입 변환

        .filter { $0 != nil }

        .flatMap { $0!.appFunctionObservable } // Observable 합병

        .share()

    }



    // 앱 내 함수 실행 결과 전달 Observable

    private var appFunctionResultSubject = PublishSubject<String>()



    // 앱 내 함수 실행 결과 전달 Observable

    var appFunctionResult: Observable<String> {

        appFunctionResultSubject.asObservable()

    }



    // KVO를 통해 JavaScript 함수 호출 이벤트 감지

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

        if keyPath == "userContentController.scriptMessageHandler" {

            let newMessageHandler = change![NSKeyValueChangeNewKey] as! WKScriptMessageHandler

            if let newViewController = newMessageHandler as? WebViewController {

                appFunctionCall = newViewController.appFunctionCall

                newViewController.appFunctionResult = appFunctionResultSubject.asObservable()

            }

        }

    }

}