背景
项目中使用了wkwebview替换了之前的uiwebview,牵扯到hybird开发,我们需要和h5交互,所以用到了wkwebviewconfiguration 中的 wkusercontentcontroller
所以初始化代码如下
1
2
3
4
5
6
7
8
9
10
11
|
wkusercontentcontroller *usercontentcontroller = [[wkusercontentcontroller alloc] init]; [usercontentcontroller addscriptmessagehandler:self name:getkeyiosandroid_action]; [usercontentcontroller addscriptmessagehandler:self name:upload_action]; // wkwebview的配置 wkwebviewconfiguration *configuration = [[wkwebviewconfiguration alloc] init]; configuration.usercontentcontroller = usercontentcontroller; _webview = [[wkwebview alloc] initwithframe:cgrectzero configuration:configuration]; _webview.navigationdelegate = self; _webview.uidelegate = self; |
getkeyiosandroid_action upload_action 分别是h5通过message handler的方式来调用oc的两个方法。
这时,就已经发生了隐患,因为
[usercontentcontroller addscriptmessagehandler:self name:getkeyiosandroid_action];
这里usercontentcontroller持有了self ,然后 usercontentcontroller 又被configuration持有,最终呗webview持有,然后webview是self的一个私有变量,所以self也持有self,所以,这个时候有循环引用的问题存在,导致界面被pop或者dismiss之后依然会存在内存中。不会被释放
当然如果你只是静态界面,或者与h5的交互的内容仅限于本页面内的内容,其实只是单纯的内存泄漏,但是,如果此时和h5的交互方法中牵扯到全局变量,或者全局的一些内容,那么就不可控制了。
我发现这个问题是因为我们web页面会监听token过期的和登录状态改变的通知,然后会刷新界面,并且重新发送请求,这一系列动作中会和用户的全局信息进行交互,所以在访问一个web页面后,切换账号登录时会发现有之前访问过的web页面请求发出,并且因为token不同报了token过期的错误,所以导致登录后误操作为token过期,紧接着被踢到登录界面。
通过charles抓包发现,这些web页面都是在切换登录账号欠访问的所有界面,所以,锁定问题时web页面依旧存在,在切换登录后收到了登录状态改变的通知,重新刷新了界面导致请求发出并返回报错,进而出现登录后被踢出的bug。
解决方案:
既然是循环引用,那么必须破除一边的强引用,改为弱引用,或者直接去除引用。思路明朗了。。
尝试1:
1
2
3
|
id __weak weakself = self; wkusercontentcontroller *usercontentcontroller = [[wkusercontentcontroller alloc] init]; [usercontentcontroller addscriptmessagehandler:weakself name:getkeyiosandroid_action]; |
思路效仿block , 结果失败
尝试2:
在viewwilldisappear / viewdiddisappear 生命周期方法中调用
1
|
[_webview.configuration.usercontentcontroller removealluserscripts]; |
这算一个脑抽的尝试,看文档说明就懂了。自行略过
尝试3:
不在初始化时添加scriptmessagehandler, 而是和notificenter/kvc一个思路
1
2
3
4
5
6
7
8
9
10
11
12
13
|
- ( void )viewwillappear:( bool )animated { [super viewwillappear:animated]; [_webview.configuration.usercontentcontroller addscriptmessagehandler:self name:getkeyiosandroid_action]; [_webview.configuration.usercontentcontroller addscriptmessagehandler:self name:upload_action]; } - ( void )viewwilldisappear:( bool )animated { [super viewwilldisappear:animated]; [_webview.configuration.usercontentcontroller removescriptmessagehandlerforname:getkeyiosandroid_action]; [_webview.configuration.usercontentcontroller removescriptmessagehandlerforname:upload_action]; } |
结果成功
小结:
之前在使用wkwebview的时候很多blog的内容都只是说了怎么添加message handler 但是并没有高速大家有这个内存泄漏的风险,如果你只是页面内的数据调用你压根都不会发现这个问题。
此坑已填!
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:https://blog.csdn.net/wxs0124/article/details/78402596