在后台模式下进行Web服务调用 - iOS

时间:2015-12-17 07:12:28

标签: ios iphone background-service location-services

我需要在每分钟调用一个Web服务,并在app处于后台状态时解析数据。

由于APP使用位置服务,我已启用后台模式以更新位置。

我尝试使用计时器后台任务调用位置更新,但它无效。

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    NSLog(@"ending background task");
    [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
    self.bgTask = UIBackgroundTaskInvalid;
    }];


    self.timer = [NSTimer scheduledTimerWithTimeInterval:60
                                              target:self.locationManager
                                            selector:@selector(startUpdatingLocation)
                                            userInfo:nil
                                             repeats:YES];
}

有没有办法以更少的电池消耗来实现这一点。

我提到this link 我没有在这里找到更好的解决方案。

1 个答案:

答案 0 :(得分:0)

<强> AppDelegate.h

#import <UIKit/UIKit.h>

@interface AppDelegate : NSObject  {
    // Instance member of our background task process
    UIBackgroundTaskIdentifier bgTask; 
}

@end

<强> AppDelegate.m

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"Application entered background state.");

    // bgTask is instance variable
    NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);

    bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [application endBackgroundTask:self->bgTask];
            self->bgTask = UIBackgroundTaskInvalid;
        });
    }];

    dispatch_async(dispatch_get_main_queue(), ^{

        if ([application backgroundTimeRemaining] > 1.0) {
            // Start background service synchronously
            [[BackgroundCleanupService getInstance] run];
        }

        [application endBackgroundTask:self->bgTask];
        self->bgTask = UIBackgroundTaskInvalid;

    });
}

上述实现中有几个关键行:

第一个是行bgTask = [application beginBackgroundTaskWithExpirationHandler ...,它要求额外的时间在后台运行清理任务。

第二个是以dispatch_async开头的委托方法的最终代码块。它基本上是通过调用[application backgroundTimeRemaining]检查是否还有时间来运行操作。在这个例子中,我想要运行一次后台服务,但是,你可以在每次迭代时使用backgroundTimeRemaining的循环检查。

行[[BackgroundCleanupService getInstance] run]将调用我们的单例服务类,我们现在将构建它。

随着app delegate准备好触发我们的后台任务,我们现在需要一个与Web服务器通信的服务类。在下面的示例中,我将发布一个虚构的会话密钥并解析JSON编码的响应。此外,我正在使用两个有用的库来发出请求并反序列化返回的JSON,特别是JSONKit和ASIHttpRequest。

BackgroundCleanupService.h

#import <Foundation/Foundation.h>

@interface BackgroundCleanupService : NSObject

+ (BackgroundCleanupService *)getInstance;

- (void)run;

@end

BackgroundCleanupService.m

#import "BackgroundCleanupService.h"
#import "JSONKit.h"
#import "ASIHTTPRequest.h"

@implementation BackgroundCleanupService

/*
 * The singleton instance. To get an instance, use
 * the getInstance function.
 */
static BackgroundCleanupService *instance = NULL;

/**
 * Singleton instance.
 */

+(BackgroundCleanupService *)getInstance {
    @synchronized(self) {
        if (instance == NULL) {
            instance = [[self alloc] init];
        }
    }
    return instance;
}

- (void)run {

    NSURL* URL = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.example.com/user/%@/endsession", @"SESSIONKEY"]];

    __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:URL];

    [request setTimeOutSeconds:20]; // 20 second timeout

    // Handle request response
    [request setCompletionBlock:^{
        NSDictionary *responseDictionary = [[request responseData] objectFromJSONData];

        // Assume service succeeded if JSON key "success" returned
        if([responseDictionary  objectForKey:@"success"]) {
                NSLog(@"Session ended");
        }
        else {
             NSLog(@"Error ending session");
        }
    }];

    // Handle request failure
    [request setFailedBlock:^{
        NSError *error = [request error];
        NSLog(@"Service error: %@", error.localizedDescription);
    }];

    // Start the request synchronously since the background service
    // is already running on a background thread
    [request startSynchronous];
}

@end
可以帮助