【问题标题】:WKWebView crashes on deinitWKWebView 在 deinit 上崩溃
【发布时间】:2016-06-02 10:18:36
【问题描述】:

我有这个层次结构 - UIViewController -> ChildUIViewController -> WKWebView。

我遇到了 WKWebView 消息处理程序的问题,该消息处理程序泄漏并阻止子视图控制器被释放。

经过一番阅读,我找到了一种通过使用此修复程序来修复保留周期的方法 - WKWebView causes my view controller to leak

现在我可以看到子视图控制器正在到达 deinit,但之后 WKWebView 在 deinit 上崩溃(Xcode 中没有有用的日志)。

任何想法或方向可能是什么问题?

谢谢

更新 这是我的代码 - Code Gist

【问题讨论】:

    标签: swift crash wkwebview


    【解决方案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 实例化了包装类的局部变量。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-29
        • 2016-07-06
        • 1970-01-01
        • 1970-01-01
        • 2016-09-07
        • 2018-10-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多