マルチペア接続フレームワーク - セッションで紛失したピアステー
-
21-12-2019 - |
質問
このマルチペア接続フレームワークが、コミュニティによって遭遇したすべてのバグを考えると、現実の世界での使用の準備ができているのだろうか。私はそれを正しく設定していると思いますが、私が同様の問題に遭遇した他のすべてのサンプルプロジェクト。
私がBonjourか何かに固有のいくつかの問題に縛られているかもしれない問題は、それを理解することはできませんが、基本的に問題は次のとおりです。
- 私は多数のピアを持つアクティブな
MCSession
を持っています。 - 今すぐデバイスがセッション中である場合、力を終了する、その「ピア」は無期限の時間に接続されているままである。
-
browser:lostPeer:
メソッドがそのピアに対して呼び出されたとしても、そのユーザーOUTを強制するためにできることは何もありません。 "近く"。 -
session:peer:didChangeState:
メソッドはそのピアに対して呼び出されません。 - その力が辞められたそのピアがアプリに戻ってきたとき、それらは
browser:foundPeer:withDiscoveryInfo:
によって再び "見つかった"ですが、それでもsession.connectedPeers
nsArrayにも存在します。明らかに彼らはまだセッションに関するデータや更新を受け取らず、実際には接続されていません。 - オリジナルのピアをセッションに
MCSessionStateNotConnected
として登録するように機能する唯一のものは、そのピアを元のセッションに再接続することです。その後、PeerIDの新しいインスタンスがsession:peer:didChangeState:
で、Peerid呼び出しの古いインスタンスがMCSessionStateConnected
の旧インスタンスの直後に、Peeridの新しいインスタンスが発生します。
サンプルチャットアプリケーションでは、この問題を詳しく説明します。 https://developer.apple。 COM /ライブラリ/ iOS / SAMPLECODE / MULTIPERGROUPCHAT /序文/ intro.html
手動で手動でピアを削除する方法はないようですので、私は何をすべきですか?どういうわけかセッションを再構築して再構築する必要がありますか?
このフレームワークは少し混乱のようなようですが、私は判断を予約しようとしています!
解決
私の唯一の問題は、セッションとピアの間に1-1の関係を持つことでした。それはブロードキャストの送信を複雑にしますが、少なくともセッション自体の切断/削除を通してピアレベルの切断とクリーンアップを可能にします。
更新
私の元の答えを詳しく説明するには、接続されているピアにデータを送信できるようにするために、ピアごとに作成されたセッションへの参照を維持する必要があります。私はこれに対して変わる辞書を使っていました。
招待状が新しいセッションで送付/受け入れられたら、MCSession
Delegateメソッドを使用して辞書を更新します。
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state {
if (state==MCSessionStateConnected){
_myPeerSessions[peerID.displayName] = session;
}
else if (state==MCSessionStateNotConnected){
//This is where the session can be disconnected without
//affecting other peers
[session disconnect];
[_myPeerSessions removeObjectForKey:peerID.displayName];
}
}
.
辞書のすべての値を返すメソッドですべてのピアにアクセスできます。
- (NSArray *)allConnectedPeers {
return [[_myPeerSessions allValues] valueForKey:@"connectedPeers"];
}
.
特定のピアまたはVIAブロードキャストへのデータの送信は、次のような方法で行うことができます。
- (void)sendData:(NSData *)data toPeerIDs:(NSArray *)remotePeers reliable:(BOOL)reliable error:(NSError *__autoreleasing *)error {
MCSessionSendDataMode mode = (reliable) ? MCSessionSendDataReliable : MCSessionSendDataUnreliable;
for (MCPeerID *peer in remotePeers){
NSError __autoreleasing *currentError = nil;
MCSession *session = _myPeerSessions[peer.displayName];
[session sendData:data toPeers:session.connectedPeers withMode:mode error:currentError];
if (currentError && !error)
*error = *currentError;
}
}
. 他のヒント
アプリケーションが閉じる前にセッションを切断しましたか?これにより、ピアをセッションから正しく削除し、ピアに割り当てられたリソースをクリーンアップする必要があります。
具体的には、[self.peer disconnect]
applicationWillTerminate:
のようなものがあることを意味します。 私は同様の問題を抱えていました。私が1つのiOSデバイスで私のアプリを実行して別のiOSデバイスで実行した場合は、次に辞めて再起動します(Xcodeから再実行したときに再起動してください)。少し後でメッセージ。これは私を捨てていました。しかし、より慎重に見て、接続されていないメッセージが実際に接続されているものよりも異なる牡羊座を意味することがわかります。
私はここでの問題は私が見たことがあるほとんどのサンプルがPeeridの展示名を気にするだけで、同じデバイス/ displaynameのために複数のピアツを得ることができるという事実を無視することです。
私は今や展示名を最初にチェックしてから、ポインタの比較を行うことによって、Peeridが同じであることを確認します。
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state {
MyPlayer *player = _players[peerID.displayName];
if ((state == MCSessionStateNotConnected) &&
(peerID != player.peerID)) {
NSLog(@"remnant connection drop");
return; // note that I don't care if player is nil, since I don't want to
// add a dictionary object for a Not Connecting peer.
}
if (player == nil) {
player = [MyPlayer init];
player.peerID = peerID;
_players[peerID.displayName] = player;
}
player.state = state;
...
. 承認された答えを取り得ることができなかったので、代わりに、ブラウザが接続されていないときに接続をリセットし、他に接続されたピアがないときに接続をリセットするためのタイマーがある。
-(void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{
//DebugLog(@"session didChangeState: %ld",state);
if(resetTimer != nil){
[resetTimer invalidate];
resetTimer = nil;
}
if(state == MCSessionStateNotConnected){
[session disconnect];
[peerSessions removeObjectForKey:peerID.displayName];
[self removeGuidyPeerWithPeerID:peerID];
//DebugLog(@"removing all guides from peer %@",peerID);
if([localSession connectedPeers].count == 0){
DebugLog(@"nothing found... maybe restart in 3 seconds");
dispatch_async(dispatch_get_main_queue(), ^{
resetTimer = [NSTimer
scheduledTimerWithTimeInterval:3.0
target:self selector:@selector(onResetTimer:)
userInfo:nil
repeats:NO];
}
);
}
}
...
.
}
Swift 3の次のコードでMcBrowserviewControllerからピアを削除できます。
self.mySession.cancelConnectPeer(self.myPeerID)
.