今天使用 addScriptMessageHandler
向 WKWebView
注入方法给 js
调用时发现有内存泄露问题。
出现问题的代码
1 | WKWebViewConfiguration *webViewConfiguration = [[WKWebViewConfiguration alloc] init]; |
原因
调用 addScriptMessageHandler
时 userContentController
会 retain self
。而 self
又间接 retain userContentController
,形成了循环引用。
解决方案
搜了下,网上已经有解决方案了。后来在 cordova-plugin-wkwebview-engine
里也看到处理这个问题。这里记录下3个解决方案。
方案1
在适当的时候调用 removeScriptMessageHandlerForName
方法。这个方案缺点时是不好找到适当的时间点,比如该 viewController
被其他地方 dismiss
这时候就不好处理。
方案2
新建一个类来代理 self
,这样 userContentController
就 retain 这个新类的对象,新类对象只是弱引用 self
,这样循环引用就解开了。
1 | @interface CDVWKWeakScriptMessageHandler : NSObject <WKScriptMessageHandler> |
1 | // CDVWKWebViewEngine.m |
方案3
该方案跟方案2基本一样,不过新类集成 NSProxy
,并把所有接收到的方法都转发给 self
。该方案使用于所有类似场景,更具通用性。
1 | // |
1 | // |
1 | WKWebViewConfiguration *webViewConfiguration = [[WKWebViewConfiguration alloc] init]; |