41

MCNearbyServiceBrowser と MCNearbyServiceAdvertiser を使用して、2 つのピアを MCSession に参加させています。MCSession の sendData メソッドを使用して、それらの間でデータを送信できます。セッションのMCSessionDelegate didChangeStateハンドラーを介してMCSessionStateNotConnectedをランダムに(そして私が制御するイベントによるものではない)受け取るまで、すべてが期待どおりに機能しているようです。さらに、MCSession の connectedPeers 配列にはピアがありません。

2 つの質問: なぜですか? MCSessionが切断されないようにするにはどうすればよいですか?

4

5 に答える 5

27

これはバグで、Apple に報告したところです。ドキュメントでは、didReceiveCertificateコールバックはオプションであると主張していますが、そうではありません。このメソッドを に追加しますMCSessionDelegate

- (void) session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler
 {
     certificateHandler(YES);
 }

ランダムな切断は停止するはずです。

于 2013-10-30T23:59:03.323 に答える
18

更新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); }
 }
于 2013-10-21T15:26:21.223 に答える
1

接続要求を受け入れた直後に切断していました。状態を観察すると、MCSessionStateConnected から MCSessionStateNotConnected に変化することがわかりました。

私は自分のセッションを作成しています:

[[MCSession alloc] initWithPeer:peerID]

セキュリティ証明書を扱うインスタンス化方法ではありません:

 - (instancetype)initWithPeer:(MCPeerID *)myPeerID securityIdentity:(NSArray *)identity encryptionPreference:(MCEncryptionPreference)encryptionPreference 

上記の Andrew のヒントに基づいて、delegate メソッドを追加しました

   - (void) session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler {
         certificateHandler(YES);
     }

そして切断は止まりました。

于 2014-09-04T19:35:10.673 に答える