WKWebView 在 deinit 上崩溃
Posted
技术标签:
【中文标题】WKWebView 在 deinit 上崩溃【英文标题】:WKWebView crashes on deinit 【发布时间】:2016-06-02 10:18:36 【问题描述】:我有这个层次结构 - UIViewController -> ChildUIViewController -> WKWebView。
我遇到了 WKWebView 消息处理程序的问题,该消息处理程序泄漏并阻止子视图控制器被释放。
经过一番阅读,我找到了一种通过使用此修复程序来修复保留周期的方法 - WKWebView causes my view controller to leak
现在我可以看到子视图控制器正在到达 deinit
,但之后 WKWebView 在 deinit
上崩溃(Xcode 中没有有用的日志)。
任何想法或方向可能是什么问题?
谢谢
更新 这是我的代码 - Code Gist
【问题讨论】:
【参考方案1】:把这个放在子视图控制器的deinit方法中:
webView.scrollView.delegate = nil
【讨论】:
哇。谢谢!我们撞到了这个,你能解释一下是怎么发现的吗? @shannoga 看起来像WKWebView
存储 __unsafe_unretained
指向您的代表的指针。有时在视图控制器释放后不会立即释放 Web 视图,这会在 Web 视图尝试通知委托时导致崩溃。【参考方案2】:
别忘了删除你添加的 WKWebView 的委托:
deinit
webView.navigationDelegate = nil
webView.scrollView.delegate = nil
看起来 WKWebView 存储了指向您的委托的 __unsafe_unretained 指针。有时当 web 视图在视图控制器释放后没有立即释放。当 Web 视图尝试通知委托某些内容时,这会导致崩溃。
【讨论】:
【参考方案3】:我尝试了与您提到的相同的方法。它非常适合我。我试过的代码是,
class CustomWKWebView : WKWebView
deinit
print("CustomWKWebView - dealloc")
class LeakAvoider : NSObject, WKScriptMessageHandler
weak var delegate : WKScriptMessageHandler?
init(delegate:WKScriptMessageHandler)
self.delegate = delegate
super.init()
func userContentController(userContentController: WKUserContentController,
didReceiveScriptMessage message: WKScriptMessage)
self.delegate?.userContentController(
userContentController, didReceiveScriptMessage: message)
deinit
print("LeakAvoider - dealloc")
class ChildViewController: UIViewController , WKScriptMessageHandler
var webView = CustomWKWebView()
override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
override func viewDidLoad()
super.viewDidLoad()
view.addSubview(webView)
webView.frame = self.view.bounds;
override func viewDidAppear(animated: Bool)
super.viewDidAppear(animated)
let url = NSURL(string: "https://appleid.apple.com")
webView.loadRequest(NSURLRequest(URL:url!))
webView.configuration.userContentController.addScriptMessageHandler(
LeakAvoider(delegate: self), name: "dummy")
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage)
deinit
print("ChaildViewController- dealloc")
webView.stopLoading()
webView.configuration.userContentController.removeScriptMessageHandlerForName("dummy")
class ViewController: UIViewController
override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
override func viewDidLoad()
super.viewDidLoad()
deinit
print("ViewController - dealloc")
弹出ViewController后的日志是:
ViewController - dealloc
ChaildViewController- dealloc
LeakAvoider - dealloc
CustomWKWebView - dealloc
更新
在您的 WebViewViewController 的 viewWillDisappear 函数中添加以下行。
webView.navigationDelegate = nil
webView.scrollView.delegate = nil
我尝试在我的代码中设置这两个委托,但它开始崩溃。将以上几行放在 ChildViewController 的 viewWillDisappear 中即可解决。
【讨论】:
感谢您所做的工作。我会检查其他原因。【参考方案4】:请记住,原因可能是对它的弱引用造成的。 我确定你已经用 WKWebView 实例化了包装类的局部变量。
【讨论】:
以上是关于WKWebView 在 deinit 上崩溃的主要内容,如果未能解决你的问题,请参考以下文章
iOS WKWebView javascript警报在ipad上崩溃
在 iOS14 上释放 wkwebview 时,发送手势事件导致崩溃
为啥即使在 WKWebView 中设置 cookie 后 SSO 也不起作用?