2016-02-20 16 views
8

Ho questa gerarchia - UIViewController -> ChildUIViewController -> WKWebView.WKWebView si blocca sul deinit

Ho riscontrato un problema con il gestore di messaggi WKWebView che è filtrato e impedito il rilascio del controller di visualizzazione figlio.

Dopo qualche lettura ho trovato un modo per risolvere il ciclo di mantenere utilizzando questa correzione - WKWebView causes my view controller to leak

Ora posso vedere che il controller della vista bambino sta raggiungendo deinit ma subito dopo che il WKWebView si blocca sul deinit (No registro utile da Xcode).

Qualsiasi idea o direzione quale potrebbe essere il problema?

Grazie

UPDATE qui è il mio codice - Code Gist

risposta

8

mettere questo metodo all'interno deinit del controller della vista bambino:

webView.scrollView.delegate = nil 
+0

Wow. Grazie! Abbiamo sbattuto la testa su questo, puoi spiegare come è stato scoperto? – shannoga

+0

@shannoga appare come 'WKWebView' memorizza il puntatore' __unsafe_unretained' sul tuo delegato. Talvolta sulla visualizzazione Web deallocata non immediatamente dopo la deallocazione del controller di visualizzazione e questo arresto anomalo si verifica quando la visualizzazione Web tenta di notificare qualcosa al delegato. –

1

ho provato con stesso modo come lei ha ricordato. Funziona perfettamente per me. Codice che ho provato è,

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") 
    } 
} 

Log dopo popping ViewController è:

ViewController - dealloc 
ChaildViewController- dealloc 
LeakAvoider - dealloc 
CustomWKWebView - dealloc 

UPDATE

Mettere sotto le linee in funzione viewWillDisappear del WebViewViewController.

webView.navigationDelegate = nil 
    webView.scrollView.delegate = nil 

Ho provato impostando questi due delegati nel mio codice e ha iniziato a bloccarsi. Risolto mettendo sopra le righe in vista WillDisappear di ChildViewController.

+0

Grazie per il lavoro che hai svolto. Controllerò per altri motivi. – shannoga

0

Ricordare che il motivo potrebbe essere causato da un debole riferimento ad esso. Sono sicuro di aver istanziato la variabile locale della classe wrapped con WKWebView.

+0

Grazie. Puoi spiegare meglio? Il problema ora sembra che WebView viene riallocato due volte – shannoga

+0

perché tenta di deallocare la variabile inesistente. Inserisci il tuo codice in sintesi, potrebbe aiutarti. – dimpiax

+0

Aggiungo un gist con il mio codice, sto per uccidermi presto :(, grazie per qualsiasi aiuto- https://gist.github.com/prep4gmat/eac0a7ce2ef006ed339d9966c14e5828 – shannoga

3

Non dimenticare di togliere i delegati di WKWebView aggiunto:

deinit { 
    webView.navigationDelegate = nil 
    webView.scrollView.delegate = nil 
} 

Sembra negozi WKWebView __unsafe_unretained puntatore al delegato . A volte, quando la vista Web viene deallocata non immediatamente dopo la deallocazione del controller di visualizzazione. Questo causa un arresto anomalo quando la visualizzazione Web tenta di notificare qualcosa al delegato.