私はその話題に大きな頭を悩ませています。新しいデータをチェックするために、Web サーバーを定期的にポーリングする必要があるアプリケーションに取り組んでいます。返された情報に基づいて、ローカル通知をユーザーにプッシュしたいと考えています。
このアプローチは、APNS に基づいてリモート サーバーが機能し、リモート通知をプッシュするという Apple のアプローチとは少し異なることを私は知っています。ただし、このアプローチを考慮に入れることができない多くの理由があります。その 1 つは、ユーザー認証メカニズムです。リモート サーバーは、セキュリティ上の理由から、ユーザーの資格情報を考慮することができません。私にできることは、ログインとフェッチのコアをクライアント (iPhone) に移動することだけです。
Apple が、アプリケーションがソケット接続 (つまり、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
尋ねる人のために、はい。Async NSURLConnection アプローチも試しました。どんなに。タイムアウト ハンドラと didFinishLoading:WithError で非同期アプローチを使用しても、同じようにクラッシュします。
私は立ち往生しています。どんなヒントでも大歓迎です。