I'm trying to create multiple WKWebView views inside of a background process and then add them to a view on the main thread once they are all done loading.
Each of the WKWebView's contains a chart rendered via javascript so the load time takes about a second per WKWebView so I'm trying to offload the processing to the background so the UI isn't blocked.
This works fine when dispatch_get_main_queue is commented out, however the ui is blocked for 5-10 seconds. Only the brown background of the WKWebView shows up, none of the contents from the webpage.
var webViews : [WKWebView] = []
var myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(myQueue, {
for i in 0...10
{
var url : NSURL? = NSURL(string:"http://google.com")
var req = NSURLRequest(URL:url!)
var webview = WKWebView(frame:CGRectMake(0, height * CGFloat(i), width, height))
webview.loadRequest(req)
webview.backgroundColor = UIColor.brownColor()
self.webViews.append(webview)
}
dispatch_async(dispatch_get_main_queue(),{
for item in self.webViews
{
self.view.addSubview(item)
}
});
});
If I change the WKWebView
to UIWebView
, there is a crash.
Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread.
Calling a UIKit method from a thread other than main thread is not allowed. WKWebView
is also a UIView
subclass. So I suggest you move setting frame and addSubView method out of the block, and put it before you call dispatch_get_global_queue
, and inside dispatch_get_global_queue
block, you load the request one by one.
Edit
To monitor if a request has finished loading, you can implement WKNavigationDelegate
's didFinishNavigation
function. You can set a counter, make the counter increase by 1 when the function is called, when the counter value is equal to 10, all webviews are fully loaded.
var counter = 0
var globalStart : NSDate?
var globalEnd : NSDate?
And in viewDidLoad
.
var start = NSDate()
for i in 0...9
{
var item = WKWebView()
item.frame = CGRectMake(0, self.view.bounds.height * CGFloat(i),
self.view.bounds.width, self.view.bounds.height)
item.navigationDelegate = self
self.scrollView.addSubview(item)
self.webViews.append(item)
}
self.scrollView.contentSize = CGSizeMake(self.view.bounds.width, (self.view.bounds.height - 50.0) * CGFloat(11))
let end = NSDate();
NSLog("creating webviews \(end.timeIntervalSinceDate(start))")
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),{
self.globalStart = NSDate()
for item in self.webViews
{
var url : NSURL? = NSURL(string:"http://google.com")
var req = NSURLRequest(URL:url!)
item.loadRequest(req)
}
});
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
counter++
println("\(counter) \(webView)")
if counter == 10 {
globalEnd = NSDate()
println(globalEnd!.timeIntervalSinceDate(globalStart!))
}
}
The result is creating webviews 1.85267299413681
, while time of loading all requests is more than 8 seconds for me. I didn't find a way to decrease the time of creating webviews, I think it takes that much of time to create those views.