您好,登錄后才能下訂單哦!
背景
項目中使用了WKWebView替換了之前的UIWebView,牽扯到Hybird開發(fā),我們需要和H5交互,所以用到了WKWebViewConfiguration 中的 WKUserContentController
所以初始化代碼如下
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的兩個方法。
這時,就已經發(fā)生了隱患,因為
[userContentController addScriptMessageHandler:self name:GetKeyiOSAndroid_Action];
這里userContentController持有了self ,然后 userContentController 又被configuration持有,最終唄webview持有,然后webview是self的一個私有變量,所以self也持有self,所以,這個時候有循環(huán)引用的問題存在,導致界面被pop或者dismiss之后依然會存在內存中。不會被釋放
當然如果你只是靜態(tài)界面,或者與H5的交互的內容僅限于本頁面內的內容,其實只是單純的內存泄漏,但是,如果此時和H5的交互方法中牽扯到全局變量,或者全局的一些內容,那么就不可控制了。
我發(fā)現(xiàn)這個問題是因為我們web頁面會監(jiān)聽token過期的和登錄狀態(tài)改變的通知,然后會刷新界面,并且重新發(fā)送請求,這一系列動作中會和用戶的全局信息進行交互,所以在訪問一個web頁面后,切換賬號登錄時會發(fā)現(xiàn)有之前訪問過的web頁面請求發(fā)出,并且因為token不同報了token過期的錯誤,所以導致登錄后誤操作為token過期,緊接著被踢到登錄界面。
通過charles抓包發(fā)現(xiàn),這些web頁面都是在切換登錄賬號欠訪問的所有界面,所以,鎖定問題時web頁面依舊存在,在切換登錄后收到了登錄狀態(tài)改變的通知,重新刷新了界面導致請求發(fā)出并返回報錯,進而出現(xiàn)登錄后被踢出的bug。
解決方案:
既然是循環(huán)引用,那么必須破除一邊的強引用,改為弱引用,或者直接去除引用。思路明朗了。。
嘗試1:
id __weak weakSelf = self; WKUserContentController *userContentController = [[WKUserContentController alloc] init]; [userContentController addScriptMessageHandler:weakSelf name:GetKeyiOSAndroid_Action];
思路效仿block , 結果失敗
嘗試2:
在viewWillDisappear / viewDidDisappear 生命周期方法中調用
[_webView.configuration.userContentController removeAllUserScripts];
這算一個腦抽的嘗試,看文檔說明就懂了。自行略過
嘗試3:
不在初始化時添加ScriptMessageHandler, 而是和Notificenter/KVC一個思路
- (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 但是并沒有高速大家有這個內存泄漏的風險,如果你只是頁面內的數(shù)據(jù)調用你壓根都不會發(fā)現(xiàn)這個問題。
此坑已填!
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。