WKWebView循环引用问题之addScriptMessageHandler

WKWebView 初始化时,有一个参数叫configuration,它是WKWebViewConfiguration类型的参数,而WKWebViewConfiguration有一个属性叫userContentController,它又是WKUserContentController类型的参数。
WKUserContentController对象有一个方法-addScriptMessageHandler:name:
初始化webView

lazy var webView: WKWebView = {
        let webCfg: WKWebViewConfiguration = WKWebViewConfiguration()
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = true
        preferences.javaScriptCanOpenWindowsAutomatically = false
        var userController: WKUserContentController = WKUserContentController()
        /// 注册JS的方法
        userController.add(self, name: "requestDeviceChannel")
        webCfg.userContentController = userController
        webCfg.preferences = preferences
        let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height), configuration: webCfg)
        webView.tintColor = .clear
        return webView
    }()
  • addScriptMessageHandler:name:有两个参数,第一个参数是userContentController的代理对象,第二个参数是JS里发送postMessage的对象。

当前控制器关闭后,这时我们会发现deinit不会被调用,也就是说控制器对象没有释放。问题就出现在:

  • 1、// addScriptMessageHandler 很容易导致循环引用

  • 2、// 控制器 强引用了WKWebView,WKWebView copy(强引用了)configuration, configuration copy (强引用了)userContentController

  • 3、// userContentController 强引用了 self (控制器)

解决:打破强引用。让userContentController的代理对象变成VKFlowWebBaseVCProxyHandler。

        /// 解决【addScriptMessageHandler】引起WKWebView循环引用
        let proxy = VKFlowWebBaseVCProxyHandler()
        proxy.webVC = self
       
         /// 注册JS的方法
       //userController.add(self, name: "requestDeviceChannel")       
        userController.add(proxy, name: "requestDeviceChannel")

VKFlowWebBaseVCProxyHandler里的webVC用weak修饰。


class VKFlowWebBaseVCProxyHandler: NSObject, WKScriptMessageHandler {
    
    weak var webVC: VKFlowWebBaseViewController?
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        VVLogger.debug(message.body)
        VVLogger.debug("VKFlowWebVCProxyHandler: message name: \(message.name)")

你可能感兴趣的:(WKWebView循环引用问题之addScriptMessageHandler)