我对这个主题感到非常头痛。我正在开发一个应用程序,需要定期轮询Web服务器,以检查是否有新数据。根据返回的信息,我希望向用户推送本地通知。
我知道这种方法与苹果所描述的略有不同,其中远程服务器完成工作,基于APNS推送远程通知。然而,有许多原因使我无法考虑采用这种方法。其中一个原因是用户认证机制。出于安全原因,远程服务器无法考虑用户凭据。我能做的就是将登录和获取核心移动到客户端(iPhone)上。
我注意到苹果为应用程序提供了一种机会,即唤醒并保持打开套接字连接(即VoIP应用程序)。
因此,我开始探索这种方式。在plist中添加所需的信息后,我能够通过在我的appDelegate中使用类似以下内容来“唤醒”我的应用程序:
然后NSOperation使用以下块代码启动后台任务:
上述代码似乎有时候是有效的,但很多其他情况下却会导致我的应用程序崩溃,日志信息如下:
我知道这种方法与苹果所描述的略有不同,其中远程服务器完成工作,基于APNS推送远程通知。然而,有许多原因使我无法考虑采用这种方法。其中一个原因是用户认证机制。出于安全原因,远程服务器无法考虑用户凭据。我能做的就是将登录和获取核心移动到客户端(iPhone)上。
我注意到苹果为应用程序提供了一种机会,即唤醒并保持打开套接字连接(即VoIP应用程序)。
因此,我开始探索这种方式。在plist中添加所需的信息后,我能够通过在我的appDelegate中使用类似以下内容来“唤醒”我的应用程序:
[[UIApplication sharedApplication] setKeepAliveTimeout:1200 handler:^{
NSLog(@"startingKeepAliveTimeout");
[self contentViewLog:@"startingKeepAliveTimeout"];
MyPushOperation *op = [[MyPushOperation alloc] initWithNotificationFlag:0 andDataSource:nil];
[queue addOperation:op];
[op release];
}];
然后NSOperation使用以下块代码启动后台任务:
#pragma mark SyncRequests
-(void) main {
NSLog(@"startSyncRequest");
[self contentViewLog:@"startSyncRequest"];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"exipiration handler triggered");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
[self cancel];
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableURLRequest *anURLRequest;
NSURLResponse *outResponse;
NSError *exitError;
NSString *username;
NSString *password;
NSLog(@"FirstLogin");
anURLRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:webserverLogin, username, password]]];
[anURLRequest setHTTPMethod:@"GET"];
[anURLRequest setTimeoutInterval:120.00];
[anURLRequest setCachePolicy:NSURLRequestReloadIgnoringCacheData];
exitError = nil;
NSData *tmpData = [NSURLConnection sendSynchronousRequest:anURLRequest returningResponse:&outResponse error:&exitError];
[anURLRequest setTimeoutInterval:120.00];
if(exitError != nil) { //somethings goes wrong
NSLog(@"somethings goes wrong");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
[self cancel];
return;
}
//do some stuff with NSData and prompt the user with a UILocalNotification
NSLog(@"AlltasksCompleted");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
[self cancel];
});
}
}
上述代码似乎有时候是有效的,但很多其他情况下却会导致我的应用程序崩溃,日志信息如下:
Exception Type: 00000020
Exception Codes: 0x8badf00d
Highlighted Thread: 3
Application Specific Information:
DemoBackApp[5977] has active assertions beyond permitted time:
{(
<SBProcessAssertion: 0xa9da0b0> identifier: UIKitBackgroundCompletionTask process: DemoBackApp[5977] permittedBackgroundDuration: 600.000000 reason: finishTask owner pid:5977 preventSuspend preventIdleSleep
)}
Elapsed total CPU time (seconds): 0.010 (user 0.010, system 0.000), 100% CPU
Elapsed application CPU time (seconds): 0.000, 0% CPU
对于那些询问的人,是的。我也尝试过异步的NSURLConnection方法。但是没有用。即使我使用带有超时处理程序和didFinishLoading:WithError的异步方法,它仍然会崩溃。
我卡住了。非常感谢任何提示。