继续在iOS中的后台启动HTTP调用

时间:2014-09-21 16:26:06

标签: ios http background nsurlconnection task

我定期对REST服务执行同步HTTP请求,以便为我的应用程序获取可能的数据更新。我在应用程序处于活动状态并且计时器完成时进行调用,这是代码片段:

__block BOOL result;

            dispatch_queue_t queue = dispatch_queue_create(UpdateQueue, NULL);
            dispatch_async(queue,^{

                UpdateMngr *updateMngr = [[UpdateMngr alloc] init];
                result = [updateMngr getUpdatedData];

                dispatch_async(dispatch_get_main_queue(), ^{
                    if (result) {
                        // Notify user update is OK
                    }
                    else {
                        // Notify user update failed
                    }
                });
            });

getUpdatedData方法的位置:

- (BOOL)getUpdatedData
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.serviceURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

NSURLResponse *response = nil;
NSError *error = nil;

NSData* jsonData = [self getRequestBody];    
[request setHTTPBody:jsonData];
NSData *content = [NSURLConnection sendSynchronousRequest:request
                                        returningResponse:&response
                                                    error:&error];

if (([content length] > 0) && (error == nil)) {
    id parseResult = [self parseJson:content];

    if ([parseResult isKindOfClass:[NSString class]]) {
        return NO;
    }
    else if ([parseResult isKindOfClass:[NSDictionary class]]) {
            @try {
                    // Success
                    // Save data in database
            }
            @catch (NSException *ex) {
                    // Handle error
            }
    }
}
else if (([content length] == 0) && (error == nil)) {
    // No updated data
    return NO;
}
else if (error != nil) {
    return NO;
}

return YES;
}

似乎进入后台或进入非活动状态,例如,来电,请求被中断,我发现有时候应用的行为就好像我期望从服务接收的数据不完整尽管我收到了回复,但只有一部分显示给用户。

我一直在阅读有关在后台执行有限长度任务的iOS App Programming Guide部分,但我不确定如何在此处应用它,因为该文档中的代码片段似乎启动了完整的任务背景,虽然我需要的是完成一个已经开始的任务...我是否应该总是在后台执行我的任务,以防万一?或者我该如何处理这种情况?我想这应该是一个非常常见的场景,但我找不到任何启发我的示例或教程。

注意:我的应用适用于 iOS 5 +

提前致谢

编辑:这是否是合适的解决方案?:

- (void)getUpdates
{
   self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
                // Clean up any unfinished task business by marking where you.
                // stopped or ending the task outright.
                [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
                self.bgTask = UIBackgroundTaskInvalid;
            }];

   __block BOOL result;

            dispatch_queue_t queue = dispatch_queue_create(UpdateQueue, NULL);
            dispatch_async(queue,^{

                UpdateMngr *updateMngr = [[UpdateMngr alloc] init];
                result = [updateMngr getUpdatedData];

                dispatch_async(dispatch_get_main_queue(), ^{
                    if (result) {
                        // Notify user update is OK
                    }
                    else {
                        // Notify user update failed
                    }
                });
            });

   // Finish background task
            if (self.bgTask != UIBackgroundTaskInvalid) {
                [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
                self.bgTask = UIBackgroundTaskInvalid;
            }
}

self.bgTask@property UIBackgroundTaskIdentifier bgTask;

的位置

1 个答案:

答案 0 :(得分:0)

您的代码很接近,但它有一个问题,因为后台任务已启动,然后立即完成(因为它在方法内部完成,但不在异步块内。请尝试此操作:

- (void)getUpdates
{
    self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            // Clean up any unfinished task business by marking where you.
            // stopped or ending the task outright.
            [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
            self.bgTask = UIBackgroundTaskInvalid;
        }];

        __block BOOL result;

        dispatch_queue_t queue = dispatch_queue_create(UpdateQueue, NULL);
        dispatch_async(queue,^{

            UpdateMngr *updateMngr = [[UpdateMngr alloc] init];
            result = [updateMngr getUpdatedData];

            dispatch_async(dispatch_get_main_queue(), ^{
                if (result) {
                    // Notify user update is OK
                }
                else {
                    // Notify user update failed
                }

                // Finish background task
                if (self.bgTask != UIBackgroundTaskInvalid) {
                    [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
                    self.bgTask = UIBackgroundTaskInvalid;
                }
            });
        });
}