I am using MoPub for ad mediation in my iOS app. I received a couple of user complaints about blocked UI when an ad is loading. I could replicate this only under certain low-quality network conditions.
My naive assumption was that all I had to do was call the MPAdView.loadAd
from a background thread via dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
, and update the UI with dispatch_async(dispatch_get_main_queue()
in the adViewDidLoadAd
delegate method (that gets called when an ad has been loaded by the MoPubSDK).
But as it turns out, this did not work - the delegate method is never called.
I traced the problem back into the MoPubSDK, where a NSURLConnection
is initialized via:
self.connection = [NSURLConnection connectionWithRequest:[self adRequestForURL:URL] delegate:self];
but the NSURLConnectionDelegate
methods (like connectionDidFinishLoading
) themselves are never called when executed on the background thread. It works when the call is made on the main thread.
I noticed that the "current mode" of [NSRunLoop currentRunLoop]
is "(none)" when executed on the background thread, but "kCFRunLoopDefaultMode" when executed on the main thread.
The NSURLConnection docs mention
For the connection to work correctly, the calling thread’s run loop must be operating in the default run loop mode.
so I tried setting it explicitly using
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[[NSDate alloc] initWithTimeIntervalSinceNow:60]];
but this had no effect.
So, what do I need to do to ensure that the NSURLConnection delegate methods get called when the connection is initialized in a background thread?