diff --git a/Stage1st/ContentViewController.swift b/Stage1st/ContentViewController.swift index f9758b9e..eb93746a 100644 --- a/Stage1st/ContentViewController.swift +++ b/Stage1st/ContentViewController.swift @@ -300,8 +300,6 @@ class S1ContentViewController: UIViewController, ImagePresenter, UserPresenter, NotificationCenter.default.removeObserver(self) webView.configuration.userContentController.removeScriptMessageHandler(forName: "stage1st") pullToActionController.stop() - webView.navigationDelegate = nil - webView.stopLoading() DDLogInfo("[ContentVC] Dealloced") } } @@ -366,7 +364,6 @@ extension S1ContentViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - let previousPresentType = presentType presentType = .none // defer from initializer to here to make sure navigationController exist (i.e. self be added to navigation stack) @@ -378,11 +375,7 @@ extension S1ContentViewController { didReceivePaletteChangeNotification(nil) // Also use this method to initialize content. - if case .image = previousPresentType { - // Note: Calling evaluateJavaScript to WKWebView will cause the content of it changed to blank before completionHandler return. That will lead to screen blink when user coming back from image viewer. - } else { - _tryToReloadWKWebViewIfPageIsBlankDueToMemoryWarning() - } + _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() } override func viewDidDisappear(_ animated: Bool) { @@ -399,7 +392,7 @@ extension S1ContentViewController { func applicationWillEnterForeground() { DDLogDebug("[ContentVC] \(self) will enter foreground begin") - _tryToReloadWKWebViewIfPageIsBlankDueToMemoryWarning() + _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() } func applicationDidEnterBackground() { @@ -761,7 +754,7 @@ extension S1ContentViewController: WKNavigationDelegate { } func webViewWebContentProcessDidTerminate(_ webView: WKWebView) { - DDLogInfo("[ContentVC] webViewWebContentProcessDidTerminate") + DDLogError("[ContentVC] webViewWebContentProcessDidTerminate") } func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { @@ -1287,14 +1280,10 @@ extension S1ContentViewController { bottomDecorateLine.isHidden = !self.finishFirstLoading.value } - func _tryToReloadWKWebViewIfPageIsBlankDueToMemoryWarning() { - // http://stackoverflow.com/questions/27809259/detecting-whether-a-wkwebview-has-blanked - webView.evaluateJavaScript("document.querySelector('body').innerHTML") { [weak self] (result, error) in - guard let strongSelf = self else { return } - guard let result = result as? String, result != "" else { - strongSelf.refreshCurrentPage(forceUpdate: !strongSelf.finishFirstLoading.value && strongSelf.viewModel.isInLastPage(), scrollType: .restorePosition) - return - } + func _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() { + guard let title = webView.title, title != "" else { + refreshCurrentPage(forceUpdate: !finishFirstLoading.value && viewModel.isInLastPage(), scrollType: .restorePosition) + return } } diff --git a/Stage1st/S1QuoteFloorViewController.swift b/Stage1st/S1QuoteFloorViewController.swift index 12a44f37..bf8d5629 100644 --- a/Stage1st/S1QuoteFloorViewController.swift +++ b/Stage1st/S1QuoteFloorViewController.swift @@ -47,6 +47,10 @@ class S1QuoteFloorViewController: UIViewController, ImagePresenter, UserPresente webView.scrollView.delegate = self webView.isOpaque = false + NotificationCenter.default.addObserver(self, + selector: #selector(applicationWillEnterForeground), + name: .UIApplicationWillEnterForeground, + object: nil) NotificationCenter.default.addObserver(self, selector: #selector(didReceivePaletteChangeNotification(_:)), name: .APPaletteDidChangeNotification, @@ -61,7 +65,6 @@ class S1QuoteFloorViewController: UIViewController, ImagePresenter, UserPresente DDLogInfo("[QuoteFloorVC] Dealloc Begin") NotificationCenter.default.removeObserver(self) webView.configuration.userContentController.removeScriptMessageHandler(forName: "stage1st") - webView.navigationDelegate = nil webView.stopLoading() DDLogInfo("[QuoteFloorVC] Dealloced") } @@ -81,7 +84,6 @@ class S1QuoteFloorViewController: UIViewController, ImagePresenter, UserPresente override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - let previousPresentType = presentType presentType = .none // defer from initializer to here to make sure navigationController exist (i.e. self be added to navigation stack) @@ -92,19 +94,13 @@ class S1QuoteFloorViewController: UIViewController, ImagePresenter, UserPresente didReceivePaletteChangeNotification(nil) - // http://stackoverflow.com/questions/27809259/detecting-whether-a-wkwebview-has-blanked - // Also use this method to initialize content. - if case .image = previousPresentType { - /// Note: Calling evaluateJavaScript to WKWebView will cause the content of it changed to blank before completionHandler return. That will lead to screen blink when user coming back from image viewer. - } else { - webView.evaluateJavaScript("document.querySelector('body').innerHTML") { [weak self] (result, error) in - guard let strongSelf = self else { return } - guard let result = result as? String, result != "" else { - strongSelf.webView.loadHTMLString(strongSelf.viewModel.generatePage(with: strongSelf.viewModel.floors), baseURL: strongSelf.viewModel.baseURL) - return - } - } - } + _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() + } + + func applicationWillEnterForeground() { + DDLogDebug("[QuoteFloorVC] \(self) will enter foreground begin") + _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() + DDLogDebug("[QuoteFloorVC] \(self) will enter foreground end") } } @@ -241,6 +237,10 @@ extension S1QuoteFloorViewController: WKNavigationDelegate { return } + func webViewWebContentProcessDidTerminate(_ webView: WKWebView) { + DDLogError("[QuoteFloor] \(#function)") + } + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { DispatchQueue.global().async { [weak self] in guard let strongSelf = self else { return } @@ -270,6 +270,13 @@ extension S1QuoteFloorViewController { return 0.0 } } + + func _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() { + guard let title = webView.title, title != "" else { + webView.loadHTMLString(viewModel.generatePage(with: viewModel.floors), baseURL: viewModel.baseURL) + return + } + } } // MARK: - Style diff --git a/Vendors/S1WebViewController/WebViewController.swift b/Vendors/S1WebViewController/WebViewController.swift index 8b69c6b4..7fbe0a32 100644 --- a/Vendors/S1WebViewController/WebViewController.swift +++ b/Vendors/S1WebViewController/WebViewController.swift @@ -62,7 +62,14 @@ class WebViewController: UIViewController, WKNavigationDelegate { updateBarItems() - NotificationCenter.default.addObserver(self, selector: #selector(didReceivePaletteChangeNotification(_:)), name: .APPaletteDidChangeNotification, object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(applicationWillEnterForeground), + name: .UIApplicationWillEnterForeground, + object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(didReceivePaletteChangeNotification(_:)), + name: .APPaletteDidChangeNotification, + object: nil) } required init?(coder aDecoder: NSCoder) { @@ -133,16 +140,14 @@ class WebViewController: UIViewController, WKNavigationDelegate { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.didReceivePaletteChangeNotification(nil) + DDLogInfo("[WebVC] view will appear") - // http://stackoverflow.com/questions/27809259/detecting-whether-a-wkwebview-has-blanked - // Also use this method to initialize content. - webView.evaluateJavaScript("document.querySelector('body').innerHTML") { [weak self] (result, error) in - guard let strongSelf = self else { return } - guard let result = result as? String, result != "" else { - strongSelf.webView.load(URLRequest(url: strongSelf.currentValidURL())) - return - } - } + _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() + } + + func applicationWillEnterForeground() { + DDLogDebug("[WebVC] \(self) will enter foreground begin") + _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() } // MARK: Layout @@ -184,7 +189,7 @@ class WebViewController: UIViewController, WKNavigationDelegate { } } - // MARK: - UIWebViewDelegate + // MARK: - WKWebViewNavigationDelegate func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { DDLogDebug("[WebVC] didCommit") updateBarItems() @@ -206,6 +211,10 @@ class WebViewController: UIViewController, WKNavigationDelegate { updateBarItems() } + func webViewWebContentProcessDidTerminate(_ webView: WKWebView) { + DDLogError("[WebVC] \(#function)") + } + // MARK: KVO override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard let newProgress = change?[NSKeyValueChangeKey.newKey] as? Float else { return } @@ -248,6 +257,13 @@ class WebViewController: UIViewController, WKNavigationDelegate { } } + func _tryToReloadWKWebViewIfPageIsBlankDueToWebKitProcessTerminated() { + guard let title = webView.title, title != "" else { + webView.load(URLRequest(url: currentValidURL())) + return + } + } + // MARK: - Notification override func didReceivePaletteChangeNotification(_ notification: Notification?) { statusBarSeparatorView.backgroundColor = APColorManager.shared.colorForKey("default.text.tint")