Resolve issue where we could have a web view deallocated before getting displayed.

This commit is contained in:
Maurice Parker 2020-09-01 18:54:46 -05:00
parent acaeb4164a
commit cf8dbb26f7
7 changed files with 94 additions and 91 deletions

View File

@ -13,7 +13,7 @@ import RSWeb
class PreloadedWebView: WKWebView { class PreloadedWebView: WKWebView {
private var isReady: Bool = false private var isReady: Bool = false
private var readyCompletion: ((PreloadedWebView) -> Void)? private var readyCompletion: (() -> Void)?
init(articleIconSchemeHandler: ArticleIconSchemeHandler) { init(articleIconSchemeHandler: ArticleIconSchemeHandler) {
let preferences = WKPreferences() let preferences = WKPreferences()
@ -44,7 +44,7 @@ class PreloadedWebView: WKWebView {
loadFileURL(ArticleRenderer.blank.url, allowingReadAccessTo: ArticleRenderer.blank.baseURL) loadFileURL(ArticleRenderer.blank.url, allowingReadAccessTo: ArticleRenderer.blank.baseURL)
} }
func ready(completion: @escaping (PreloadedWebView) -> Void) { func ready(completion: @escaping () -> Void) {
if isReady { if isReady {
completeRequest(completion: completion) completeRequest(completion: completion)
} else { } else {
@ -89,10 +89,10 @@ extension PreloadedWebView: WKNavigationDelegate {
private extension PreloadedWebView { private extension PreloadedWebView {
func completeRequest(completion: @escaping (PreloadedWebView) -> Void) { func completeRequest(completion: @escaping () -> Void) {
isReady = false isReady = false
navigationDelegate = nil navigationDelegate = nil
completion(self) completion()
} }
} }

View File

@ -86,9 +86,7 @@ class WebViewProviderDequeueOperation: MainThreadOperation {
func run() { func run() {
if let webView = queue.lastObject as? PreloadedWebView { if let webView = queue.lastObject as? PreloadedWebView {
webView.ready { preloadedWebView in self.completion(webView)
self.completion(preloadedWebView)
}
self.queue.remove(webView) self.queue.remove(webView)
self.operationDelegate?.operationDidComplete(self) self.operationDelegate?.operationDidComplete(self)
return return
@ -98,9 +96,7 @@ class WebViewProviderDequeueOperation: MainThreadOperation {
let webView = PreloadedWebView(articleIconSchemeHandler: articleIconSchemeHandler) let webView = PreloadedWebView(articleIconSchemeHandler: articleIconSchemeHandler)
webView.preload() webView.preload()
webView.ready { preloadedWebView in self.completion(webView)
self.completion(preloadedWebView)
}
self.operationDelegate?.operationDidComplete(self) self.operationDelegate?.operationDidComplete(self)
} }

View File

@ -452,37 +452,41 @@ private extension WebViewController {
sceneModel?.webViewProvider?.dequeueWebView() { webView in sceneModel?.webViewProvider?.dequeueWebView() { webView in
// Add the webview webView.ready {
webView.translatesAutoresizingMaskIntoConstraints = false
self.view.insertSubview(webView, at: 0)
NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: webView.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: webView.trailingAnchor),
self.view.topAnchor.constraint(equalTo: webView.topAnchor),
self.view.bottomAnchor.constraint(equalTo: webView.bottomAnchor)
])
// UISplitViewController reports the wrong size to WKWebView which can cause horizontal // Add the webview
// rubberbanding on the iPad. This interferes with our UIPageViewController preventing webView.translatesAutoresizingMaskIntoConstraints = false
// us from easily swiping between WKWebViews. This hack fixes that. self.view.insertSubview(webView, at: 0)
webView.scrollView.contentInset = UIEdgeInsets(top: 0, left: -1, bottom: 0, right: 0) NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: webView.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: webView.trailingAnchor),
self.view.topAnchor.constraint(equalTo: webView.topAnchor),
self.view.bottomAnchor.constraint(equalTo: webView.bottomAnchor)
])
webView.scrollView.setZoomScale(1.0, animated: false) // UISplitViewController reports the wrong size to WKWebView which can cause horizontal
// rubberbanding on the iPad. This interferes with our UIPageViewController preventing
// us from easily swiping between WKWebViews. This hack fixes that.
webView.scrollView.contentInset = UIEdgeInsets(top: 0, left: -1, bottom: 0, right: 0)
self.view.setNeedsLayout() webView.scrollView.setZoomScale(1.0, animated: false)
self.view.layoutIfNeeded()
// Configure the webview self.view.setNeedsLayout()
webView.navigationDelegate = self self.view.layoutIfNeeded()
webView.uiDelegate = self
webView.scrollView.delegate = self
// self.configureContextMenuInteraction()
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked) // Configure the webview
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasShown) webView.navigationDelegate = self
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.showFeedInspector) webView.uiDelegate = self
webView.scrollView.delegate = self
// self.configureContextMenuInteraction()
self.renderPage(webView) webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasShown)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.showFeedInspector)
self.renderPage(webView)
}
} }

View File

@ -246,28 +246,31 @@ private extension WebViewController {
sceneModel?.webViewProvider?.dequeueWebView() { webView in sceneModel?.webViewProvider?.dequeueWebView() { webView in
// Add the webview webView.ready {
self.webView = webView
webView.translatesAutoresizingMaskIntoConstraints = false // Add the webview
self.view.addSubview(webView, positioned: .below, relativeTo: self.statusBarView) self.webView = webView
NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: webView.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: webView.trailingAnchor),
self.view.topAnchor.constraint(equalTo: webView.topAnchor),
self.view.bottomAnchor.constraint(equalTo: webView.bottomAnchor)
])
webView.navigationDelegate = self webView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(webView, positioned: .below, relativeTo: self.statusBarView)
NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: webView.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: webView.trailingAnchor),
self.view.topAnchor.constraint(equalTo: webView.topAnchor),
self.view.bottomAnchor.constraint(equalTo: webView.bottomAnchor)
])
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked) webView.navigationDelegate = self
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasShown)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.mouseDidEnter)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.mouseDidExit)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.showFeedInspector)
self.renderPage(webView) webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasShown)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.mouseDidEnter)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.mouseDidExit)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.showFeedInspector)
self.renderPage(webView)
}
} }
} }

View File

@ -12,7 +12,7 @@ import WebKit
class PreloadedWebView: WKWebView { class PreloadedWebView: WKWebView {
private var isReady: Bool = false private var isReady: Bool = false
private var readyCompletion: ((PreloadedWebView) -> Void)? private var readyCompletion: (() -> Void)?
init(articleIconSchemeHandler: ArticleIconSchemeHandler) { init(articleIconSchemeHandler: ArticleIconSchemeHandler) {
let preferences = WKPreferences() let preferences = WKPreferences()
@ -38,7 +38,7 @@ class PreloadedWebView: WKWebView {
loadFileURL(ArticleRenderer.blank.url, allowingReadAccessTo: ArticleRenderer.blank.baseURL) loadFileURL(ArticleRenderer.blank.url, allowingReadAccessTo: ArticleRenderer.blank.baseURL)
} }
func ready(completion: @escaping (PreloadedWebView) -> Void) { func ready(completion: @escaping () -> Void) {
if isReady { if isReady {
completeRequest(completion: completion) completeRequest(completion: completion)
} else { } else {
@ -66,10 +66,10 @@ extension PreloadedWebView: WKNavigationDelegate {
private extension PreloadedWebView { private extension PreloadedWebView {
func completeRequest(completion: @escaping (PreloadedWebView) -> Void) { func completeRequest(completion: @escaping () -> Void) {
isReady = false isReady = false
navigationDelegate = nil navigationDelegate = nil
completion(self) completion()
} }
} }

View File

@ -483,37 +483,41 @@ private extension WebViewController {
coordinator.webViewProvider.dequeueWebView() { webView in coordinator.webViewProvider.dequeueWebView() { webView in
// Add the webview webView.ready {
webView.translatesAutoresizingMaskIntoConstraints = false
self.view.insertSubview(webView, at: 0)
NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: webView.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: webView.trailingAnchor),
self.view.topAnchor.constraint(equalTo: webView.topAnchor),
self.view.bottomAnchor.constraint(equalTo: webView.bottomAnchor)
])
// UISplitViewController reports the wrong size to WKWebView which can cause horizontal // Add the webview
// rubberbanding on the iPad. This interferes with our UIPageViewController preventing webView.translatesAutoresizingMaskIntoConstraints = false
// us from easily swiping between WKWebViews. This hack fixes that. self.view.insertSubview(webView, at: 0)
webView.scrollView.contentInset = UIEdgeInsets(top: 0, left: -1, bottom: 0, right: 0) NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: webView.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: webView.trailingAnchor),
self.view.topAnchor.constraint(equalTo: webView.topAnchor),
self.view.bottomAnchor.constraint(equalTo: webView.bottomAnchor)
])
webView.scrollView.setZoomScale(1.0, animated: false) // UISplitViewController reports the wrong size to WKWebView which can cause horizontal
// rubberbanding on the iPad. This interferes with our UIPageViewController preventing
// us from easily swiping between WKWebViews. This hack fixes that.
webView.scrollView.contentInset = UIEdgeInsets(top: 0, left: -1, bottom: 0, right: 0)
self.view.setNeedsLayout() webView.scrollView.setZoomScale(1.0, animated: false)
self.view.layoutIfNeeded()
// Configure the webview self.view.setNeedsLayout()
webView.navigationDelegate = self self.view.layoutIfNeeded()
webView.uiDelegate = self
webView.scrollView.delegate = self
self.configureContextMenuInteraction()
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked) // Configure the webview
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasShown) webView.navigationDelegate = self
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.showFeedInspector) webView.uiDelegate = self
webView.scrollView.delegate = self
self.configureContextMenuInteraction()
self.renderPage(webView) webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasShown)
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.showFeedInspector)
self.renderPage(webView)
}
} }

View File

@ -86,9 +86,7 @@ class WebViewProviderDequeueOperation: MainThreadOperation {
func run() { func run() {
if let webView = queue.lastObject as? PreloadedWebView { if let webView = queue.lastObject as? PreloadedWebView {
webView.ready { preloadedWebView in self.completion(webView)
self.completion(preloadedWebView)
}
self.queue.remove(webView) self.queue.remove(webView)
self.operationDelegate?.operationDidComplete(self) self.operationDelegate?.operationDidComplete(self)
return return
@ -98,9 +96,7 @@ class WebViewProviderDequeueOperation: MainThreadOperation {
let webView = PreloadedWebView(articleIconSchemeHandler: articleIconSchemeHandler) let webView = PreloadedWebView(articleIconSchemeHandler: articleIconSchemeHandler)
webView.preload() webView.preload()
webView.ready { preloadedWebView in self.completion(webView)
self.completion(preloadedWebView)
}
self.operationDelegate?.operationDidComplete(self) self.operationDelegate?.operationDidComplete(self)
} }