【问题标题】:Continuing an already started HTTP call in background in iOS在 iOS 后台继续已经启动的 HTTP 调用
【发布时间】:2014-09-21 16:26:06
【问题描述】:

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

__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 关于在后台执行有限长度任务的部分,但我不确定如何在此处应用它,因为该文档中的代码 sn-p 似乎启动了完整的任务背景,而我需要完成一项已经开始的任务......我是否应该总是在后台执行我的任务,以防万一?或者我该如何处理这种情况?我想这应该是一个很常见的场景,但我没有找到任何启​​发我的示例或教程。

注意:我的应用适用于 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;

【问题讨论】:

  • 你正在异步运行你的任务,所以你有一整套在后台线程上运行的代码。从告诉应用程序的角度启动“后台”任务并不意味着它将以不同的方式运行,除非应用程序失去其作为前台应用程序的状态。你看到“背景”的多种含义之间的区别了吗?
  • @Wain 你是对的......当我在这里说background 时,我的意思是成为后台应用程序(或非活动......)
  • 您编写代码以在适当的时候处理应用程序在后台,但您无需在创建任务之前检查它是否真的在后台。
  • @Wain 那么,如果任务启动,然后应用程序在任务完成之前进入后台或非活动状态......我该怎么办?
  • 您应该已经编写了这样的代码,以便在应用程序进入后台时后台任务可以继续。这意味着在异步进程之前启动后台任务并在完成后完成。

标签: ios http background nsurlconnection task


【解决方案1】:

您的代码已关闭,但存在问题,因为后台任务已启动然后立即完成(因为它是在方法内部完成的,而不是在异步块内部完成。试试这个:

- (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;
                }
            });
        });
}

【讨论】:

    猜你喜欢
    • 2017-10-12
    • 2023-03-23
    • 2013-07-27
    • 2016-01-13
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    相关资源
    最近更新 更多