views:

879

answers:

1

All UIWebViews share a single web thread.

When one of them is init-ed, removed from superview etc., they will attempt to lock the web thread from the main thread in a blocking fashion, thus temporarily freezing the run loop of the main thread.

If the web thread is busy, e.g. while doing a long synchronous XMLHttpRequest, this may block the main thread for a long time.

Is there a way to avoid this?

If I could modify UIWebView, I'd just make the lock attempt non-blocking, but obviously that's not the case, so I'm looking for other clever ideas.

+2  A: 

The long and short of it is: avoid doing anything that blocks the web thread for a significant amount of time (window.alert, window.prompt, XMLHttpRequest.open('GET', url, false), possibly others)

Also, avoid calling methods that lock the web thread and then immediately doing something that takes a long time as the web thread is only unlocked once control is returned to the run loop. (Example: call -[UITextView setText:] then read a file synchronously on the main thread)

rpetrich
So what happens in MobileSafari if a page does a slow synchronous XHR? I haven't tested it, but does it just freeze or what?
Jaka Jančar
It aquires the web thread's lock for the duration of the request. If the main thread then attempts to acquire the lock, it will have to wait for the request to complete (or timeout)
rpetrich
Also, I should mention that if you use an asynchronous XHR, this will no longer be an issue (ie xhr.open('GET', url, true))
rpetrich
The function making the XHR *must* appear as a simple function call (with a return value), not an asynchronous trigger/callback function, unfortunately :/
Jaka Jančar
In other words, it must block Javascript execution. I want to avoid it blocking the main thread too.
Jaka Jančar
It's difficult to prevent the main thread from acquiring the web thread lock as most methods on UITextView, UITextField and UIWebView require it, but you can make your javascript APIs asynchronous and still not too ugly:MyAPI.MyMethod(param1, function(r) { document.getElementById('result').innerText = r; });
rpetrich