更新Apple へのサポート チケットを使用した後、彼らは sendData を頻繁に呼び出し、データが多すぎると切断が発生する可能性があることを確認しました。
ブレークポイントに到達したときやバックグラウンドで切断されたことがあります。アプリ ストアではブレーク ポイントが発生しないため、アプリがバックグラウンドに入ろうとしているときにバックグラウンド タスクを開始して、バックグラウンド ケースを処理する必要があります。アプリがフォアグラウンドに戻ったら、このタスクを終了します。iOS 7 では、これにより約 3 分のバックグラウンド時間が得られます。これは、何もないよりはましです。
追加の戦略は、バックグラウンド時間が切れる 15 秒前に を使用してローカル通知をスケジュールする[[UIApplication sharedApplication] backgroundTimeRemaining]
ことです。これにより、アプリが一時停止してマルチピア フレームワークをシャットダウンする前に、ユーザーをアプリに戻すことができます。おそらく、ローカル通知は、セッションが 10 秒程度で期限切れになることを警告するでしょう...
バックグラウンド タスクが期限切れになり、アプリがまだバックグラウンドにある場合は、マルチピア接続に関連するすべてのものを破棄する必要があります。そうしないと、クラッシュが発生します。
- (void) createExpireNotification
{
[self killExpireNotification];
if (self.connectedPeerCount != 0) // if peers connected, setup kill switch
{
NSTimeInterval gracePeriod = 20.0f;
// create notification that will get the user back into the app when the background process time is about to expire
NSTimeInterval msgTime = UIApplication.sharedApplication.backgroundTimeRemaining - gracePeriod;
UILocalNotification* n = [[UILocalNotification alloc] init];
self.expireNotification = n;
self.expireNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:msgTime];
self.expireNotification.alertBody = TR(@"Text_MultiPeerIsAboutToExpire");
self.expireNotification.soundName = UILocalNotificationDefaultSoundName;
self.expireNotification.applicationIconBadgeNumber = 1;
[UIApplication.sharedApplication scheduleLocalNotification:self.expireNotification];
}
}
- (void) killExpireNotification
{
if (self.expireNotification != nil)
{
[UIApplication.sharedApplication cancelLocalNotification:self.expireNotification];
self.expireNotification = nil;
}
}
- (void) applicationWillEnterBackground
{
self.taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
{
[self shutdownMultiPeerStuff];
[[UIApplication sharedApplication] endBackgroundTask:self.taskId];
self.taskId = UIBackgroundTaskInvalid;
}];
[self createExpireNotification];
}
- (void) applicationWillEnterForeground
{
[self killExpireNotification];
if (self.taskId != UIBackgroundTaskInvalid)
{
[[UIApplication sharedApplication] endBackgroundTask:self.taskId];
self.taskId = UIBackgroundTaskInvalid;
}
}
- (void) applicationWillTerminate
{
[self killExpireNotification];
[self stop]; // shutdown multi-peer
}
また、Apple のバグにより、MCSession デリゲートでこのハンドラーが必要になる場合があります。
- (void) session:(MCSession*)session didReceiveCertificate:(NSArray*)certificate fromPeer:(MCPeerID*)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler
{
if (certificateHandler != nil) { certificateHandler(YES); }
}