问题描述
我需要每分钟调用一次Web服务,并在应用程序处于后台状态时解析数据.
I need to call a web service in every minute and parse the data when app is in background state.
由于APP使用了位置服务,因此我启用了后台模式来更新位置.
Since the APP uses location service I have enabled background mode for update Location.
我尝试通过使用计时器后台任务来调用位置更新,但是它不起作用.
I tried calling location update by using a timer background task, but it not working.
- (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];
}
有没有办法以更少的电池消耗来实现这一目标.
Is there any way to implement this with less battery consumption.
我提到了我不知道哪种解决方案更好.
I referred this linkI'm not getting which solution is better here.
推荐答案
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;
});
}
上面的实现中有几行要点:
There are couple key lines in the above implementation:
第一行是bgTask = [application beginBackgroundTaskWithExpirationHandler ...,这需要额外的时间在后台运行清理任务.
The first is the line bgTask = [application beginBackgroundTaskWithExpirationHandler..., which requests additional time to run clean up tasks in the background.
第二个是委托方法的最后代码块,以dispatch_async开头.基本上,这是检查是否还有时间通过调用[application backgroundTimeRemaining]
运行操作.在此示例中,我希望只运行一次后台服务,但也可以在每次迭代中对backgroundTimeRemaining使用循环检查.
The second is the final code block of the delegate method beginning with dispatch_async. It's basically checking whether there's time left to run an operation via the call [application backgroundTimeRemaining]
. In this example, I'm looking to run the background service once but alternatively, you can use a loop checking on the backgroundTimeRemaining on each iteration.
[[BackgroundCleanupService getInstance] run]行将是对我们现在将要构建的单例服务类的调用.
The line [[BackgroundCleanupService getInstance] run] will be a call to our singleton service class, which we'll build right now.
当应用程序委托准备触发我们的后台任务时,我们现在需要一个将与Web服务器通信的服务类.在以下示例中,我将发布一个虚拟会话密钥并解析一个JSON编码的响应.另外,我正在使用两个有用的库来发出请求并反序列化返回的JSON,特别是JSONKit和ASIHttpRequest.
With the app delegate ready to trigger our background task, we now need a service class that will communicate with the web server. In the following example, I'm going to a post a fictitious session key and parse a JSON encoded response. Also, I'm using two helpful libraries to make the request and deserialize the returned JSON, specifically JSONKit and ASIHttpRequest.
BackgroundCleanupService.h
BackgroundCleanupService.h
#import <Foundation/Foundation.h>
@interface BackgroundCleanupService : NSObject
+ (BackgroundCleanupService *)getInstance;
- (void)run;
@end
BackgroundCleanupService.m
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
可能会得到帮助
这篇关于后台模式下的Web服务调用-iOS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!