Because I could just find some outdated information / not working solutions to my problem I decided to ask this kind of question again. (See outdated / wrong solutions:)
My app is separated in one native part and one HTML part. The HTML is saved as a local file (index.html) and should be load into the myWebView
view.
@IBOutlet weak var myWebView: UIWebView! func loadWebview() { let url = Bundle.main.url(forResource: "index", withExtension: "html") let request = URLRequest(url: url!) myWebView.loadRequest(request) myWebView.scrollView.isScrollEnabled = false myWebView.allowsLinkPreview = false myWebView.delegate = self }
Because my DOM tree is very large, switching from the native part to the web part (on button click) takes quite a long time at -least for the first time switching- because afterward, I'm sure the webView-request gets cached.
To my question
: How can I preload the WebView on app init to avoid the white screen (maybe 0.5s - 1s duration) when switching from the native to the Web part?
EDIT:
The WKWebView is displaying the scrollbar while the UIWebView was not!
Using (like with UIWebView) this styles:
::-webkit-scrollbar { display: none; }
is not working and adding these lines:
webview.scrollView.showsHorizontalScrollIndicator = false webview.scrollView.showsVerticalScrollIndicator = false
is also not working at all.
1 Answers
Answers 1
Firstly, you should switch to WKWebView
, UIVewView
is no longer recommended to be used by Apple.
Secondly, you can create a pool of web views that get created and asked to load when the app starts. This way by the time the user switches to the web interface the web view might've got a chance to fully load.
For this you can use a class like this:
/// Keeps a cache of webviews and starts loading them the first time they are queried class WebViewPreloader { var webviews = [URL: WKWebView]() /// Registers a web view for preloading. If an webview for that URL already /// exists, the web view reloads the request /// /// - Parameter url: the URL to preload func preload(url: URL) { webview(for: url).load(URLRequest(url: url)) } /// Creates or returns an already cached webview for the given URL. /// If the webview doesn't exist, it gets created and asked to load the URL /// /// - Parameter url: the URL to prefecth /// - Returns: a new or existing web view func webview(for url: URL) -> WKWebView { if let cachedWebView = webviews[url] { return cachedWebView } let webview = WKWebView(frame: .zero) webview.load(URLRequest(url: url)) webviews[url] = webview return webview } }
and ask it to preload the url sometimes during the app startup:
// extension added for convenience, as we'll use the index url in at least // two places extension Bundle { var indexURL: URL { return self.url(forResource: "index", withExtension: "html")! } } webviewPreloader.preload(url: Bundle.main.indexURL)
Thirdly, you might need to use a container view instead of the actual web view, in your controller:
@IBOutlet weak var webviewContainer: UIView!
What remains is to add the preloaded web view to the container when needed:
func loadWebview() { // retrieve the preloaded web view, add it to the container let webview = webviewPreloader.webview(for: Bundle.main.indexURL) webview.frame = webviewContainer.bounds webview.translatesAutoresizingMaskIntoConstraints = true webview.autoresizingMask = [.flexibleWidth, .flexibleHeight] webviewContainer.addSubview(webview) }
And not lastly, be aware that keeping alive instances of web views, might carry performance penalties - memory and CPU-wise.
0 comments:
Post a Comment