在后台线程上未调用NSURLConnectionDelegate方法

时间:2015-12-01 14:09:13

标签: ios nsurlconnection grand-central-dispatch nsrunloop mopub

我在iOS应用中使用MoPub进行广告调解。我收到了一些用户对广告加载时阻止用户界面的投诉。我只能在某些低质量的网络条件下复制这个。

我天真的假设是我所要做的只是通过MPAdView.loadAd从后台线程调用dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{,并使用dispatch_async(dispatch_get_main_queue()代表中的adViewDidLoadAd更新用户界面方法(在MoPubSDK加载广告时调用)。

但事实证明,这不起作用 - 委托方法永远不会被调用。

我将问题追溯到MoPubSDK,其中NSURLConnection通过以下方式初始化:

self.connection = [NSURLConnection connectionWithRequest:[self adRequestForURL:URL] delegate:self];

但是NSURLConnectionDelegate方法(如connectionDidFinishLoading)本身在后台线程上执行时从不被调用。它在主线程上进行调用时有效。

我注意到"当前模式" [NSRunLoop currentRunLoop]是"(无)"当在后台线程上执行时,但是" kCFRunLoopDefaultMode"在主线程上执行时。

NSURLConnection文档提到

  

为使连接正常工作,调用线程的运行循环必须以默认的运行循环模式运行。

所以我尝试使用

明确设置它
 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[[NSDate alloc] initWithTimeIntervalSinceNow:60]];

但这没有效果。

那么,我需要做些什么来确保在后台线程中初始化连接时调用NSURLConnection委托方法?

2 个答案:

答案 0 :(得分:0)

好的,经过几个小时的搜索,我写了这个问题 - 当然,15分钟后,我在SO找到了一个可能的解决方案......

self.connection = [[NSURLConnection alloc] initWithRequest:[self adRequestForURL:URL] delegate:self startImmediately:NO];

NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
[self.connection scheduleInRunLoop:runLoop forMode:NSRunLoopCommonModes];
[self.connection start];
[runLoop run];

这可确保调用NSURLConnection委托方法。

(我现在有一个不同的问题"这可能是从辅助线程调用UIKit的结果。" - 但这与原始问题无关。)

答案 1 :(得分:0)

您可能应该在主运行循环而不是当前循环上调度连接对象。这不仅可以避免在非功能运行循环上安排它的问题(这是什么?),而且还将确保在请求完成时,广告框架不会尝试在错误的线程上执行UI操作。