在后台调用http请求在调度串行队列中失败

时间:2013-06-17 04:58:28

标签: objective-c asynchronous httprequest

每当异步找到新位置时我都会发出一个http请求,为了处理请求,我创建了一个名为后台请求者的类来处理所有这些请求。以下代码示例如下:

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
               fromLocation:(CLLocation *)oldLocation
{
 dispatch_queue_t queue;
            queue = dispatch_queue_create("com.test.sample", NULL); //create a serial queue can either be null or DISPATCH_QUEUE_SERIAL


            dispatch_async(queue,
                ^{

                if (bgTask == UIBackgroundTaskInvalid)
                {
                    bgTask=[[UIApplication sharedApplication]
                            beginBackgroundTaskWithExpirationHandler:
                            ^{
                                DDLogInfo(@"Task =%d",bgTask);
                                DDLogInfo(@"Ending bground task due to time expiration");
                                [[UIApplication sharedApplication] endBackgroundTask:bgTask];

                                bgTask = UIBackgroundTaskInvalid;
                            }];

                }

                BackgroundRequester *request = [[BackgroundRequester alloc] initwithLocation:self.currentLocation];

                [request start];

                DDLogInfo(@"Task =%d",bgTask);

                DDLogInfo(@"bg Task remaining time=%f",[[UIApplication sharedApplication] backgroundTimeRemaining]);

                });

}


//background requester class

//the start function will inturn calll the callAsynchrnously method.

-(void) callAsynchronously:(NSString *)url
{
    DDLogInfo(@"Calling where am i from background");
    DDLogInfo(@"Url =%@",reqURL);

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:20.0f];

    responseData = [[NSMutableData alloc] init];
    connect = [NSURLConnection connectionWithRequest:request delegate:self];
    [connect start];
}

1 个答案:

答案 0 :(得分:1)

您无法在后台队列中使用connectionWithRequest(无需在某些runloop中安排连接)。任

  • 使用sendSynchronousRequest(如果你从这样的后台队列中使用它就可以了,或者

  • 在运行循环中安排连接。如果你仔细研究AFNetworking代码,你会发现它们在专用线程上创建了一个运行循环,如果你真的需要NSURLConnectionDataDelegate方法,这将成为最优雅的解决方案。

    您也可以使用主循环(虽然我对该解决方案不那么疯狂),例如:

    connect = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [connect scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    [connect start];
    

    另请注意,我没有使用connectionWithRequest(因为它会立即启动连接,这与您对start的调用不兼容;如果您使用{{1},则仅使用start initWithRequest startImmediately的{​​{1}}。如果您尝试将NOstart结合使用,可能会导致问题。

我认为connectionWithRequest最简单(并且不必编写任何sendSynchronousRequest方法)。但是,如果您需要NSURLConnectionDataDelegate方法(例如,您需要进度更新,您正在使用流媒体协议等),请使用scheduleInRunLoop方法。