In my iPhone app I'm using a 3rd party library (libPusher) for WebSockets networking and this library causes every UIScrollView component in my app to become unresponsive. This includes UIScrollViews and UITableView.
What happens is that if a user scrolls one of the UIScrollView components with his finger and happens to keep touching and sliding the view with his finger at the same time that a network operation is under way, then this leads to a completely unresponsive UIScrollView that stops accepting touch events (it thinks that it's in a drag mode all the time even when the finger is lift) and does not decelerate appropriately. The only way out is to destroy the UIScrollView and recreate a new one.
I have contacted the developer of the library but unfortunately so far haven't heard back.
From what I read, this is a common problem when running a run-loop in an un-appropriate mode such as NSDefaultRunLoopMode
, however this library seems to be doing the right thing and it runs its run loop in NSRunLoopCommonModes
so I'm unclear as what the right solution is.
I tried playing with different modes (tried NSDefaultRunLoopMode
) but the behavior is the same.
I'm using iOS 5 and it's the same behavior on the simulator as well as on devices.
Let me paste the code which I think is problematic in the lib and hopefully that'd be enough scope to let you help me find a solution.
In a subclass of NSOperation we have:
- (void)start
{
NSAssert(URLRequest, @"Cannot start URLRequestOperation without a NSURLRequest.");
[self setExecuting:YES];
URLConnection = [[NSURLConnection alloc] initWithRequest:URLRequest delegate:self startImmediately:NO];
if (URLConnection == nil) {
[self setFinished:YES];
}
// Common modes instead of default so it won't stall uiscrollview scrolling
[URLConnection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[URLConnection start];
do {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
} while (!_isFinished);
}
This operation runs on the main thread, as in [[NSOperationQueue mainQueue] addOperation:authOperation];
. (maybe this is the problem, but I tried running it in another thread and it crashes so the library will need more work to make it background-thread safe so I can't prove yet that this is the solution...)
So far I tried
- changing the run loop mode to
NSDefaultRunLoopMode
- didn't help. - running the operation in a new operation queue that I created (e.g. not on the main thread) but the library doesn't seem to be ready for this as it crashes.
I still feel like I'm shooting in the dark... help :)
thanks!