我有这个层次结构 - UIViewController - > ChildUIViewController - > WKWebView。
我遇到了WKWebView消息处理程序的问题,该处理程序泄露并阻止子视图控制器被释放。
经过一些阅读后,我找到了一种方法来修复保留周期,使用此修复程序 - WKWebView causes my view controller to leak
现在我可以看到子视图控制器到达deinit
但是之后WKWebView正在deinit
崩溃(没有来自Xcode的有用日志)。
任何想法或方向可能是什么问题?
由于
更新 这是我的代码 - Code Gist
答案 0 :(得分:10)
将此内容放在子视图控制器的deinit方法中:
'Validators.composeAsync(ValidationService.checkUserName)'
答案 1 :(得分:4)
不要忘记删除您添加的WKWebView代表:
deinit {
webView.navigationDelegate = nil
webView.scrollView.delegate = nil
}
看起来WKWebView将__unsafe_unretained指针存储到您的委托中。有时,在视图控制器释放后,web视图不会立即解除分配。当Web视图尝试通知委托时,这会导致崩溃。
答案 2 :(得分:1)
我尝试的方式和你提到的一样。它对我来说很完美。我试过的代码是,
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中解决。
答案 3 :(得分:0)
请记住,原因可能是由弱引用引起的。 我确定你已经使用WKWebView实例化了包装类的局部变量。