Multipeer连接框架 – 丢失的对端停留在Session中

我想知道这个Multipeer连接框架是否准备好在现实世界中使用,考虑到社区遇到的所有错误。 我想我正在设置它,但我尝试过的所有其他示例项目都遇到类似的问题。

我遇到的问题可能与Bonjour固有的一些问题有关,我无法弄清楚,但基本上问题如下:

  • 我有一个活跃的MCSession与一些同龄人。
  • 现在,如果一个设备正在一个会话中,然后强制退出 ,那么“对等”将保持无限期的连接状态。
  • 即使browser:lostPeer:方法被该对等方调用,甚至不再在浏览器中显示为“Nearby”,我也无法强制该用户出去。
  • session:peer:didChangeState:方法不被该对等方调用。
  • 当强制退出的对等方回到应用程序时, browser:foundPeer:withDiscoveryInfo:再次“find” browser:foundPeer:withDiscoveryInfo:但仍存在于session.connectedPeers NSArray中。 很明显,他们还没有收到有关会议的任何数据或更新,实际上并没有连接。
  • 唯一似乎将原始对等体注册为MCSessionStateNotConnected到会话的工作是将该对等MCSessionStateNotConnected连接到原始会话。 然后session:peer:didChangeState:重复呼叫session:peer:didChangeState:其中peerID的新实例是MCSessionStateConnected并在peerID的旧实例调用MCSessionStateNotConnected

示例聊天应用程序很好地演示了这个问题: https : //developer.apple.com/library/ios/samplecode/MultipeerGroupChat/Introduction/Intro.html

由于似乎没有任何方法可以手动强制从会话中删除对等方,我该怎么办? 我应该尝试重build会议吗?

这个框架似乎有点混乱,但我试图保留判断!

我对这类问题的唯一解决方法是在会话和对等点之间build立一个1-1关系。 它使发送广播变得复杂,但是至less允许通过断开/删除会话本身来进行同级断开和清除。

更新

为了详细说明我的原始答案,为了能够将数据发送给连接的对等体,必须保持对为每个对等体创build的会话的引用。 我一直在使用这个可变的字典。

一旦邀请已被发送/接受一个新的会话,使用MCSession委托方法来更新字典:

 - (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]; } } 

所有对等点都可以通过返回字典的所有值的方法来访问,并且每个MCSession又包含所有connectedPeers (本例中为1):

 - (NSArray *)allConnectedPeers { return [[_myPeerSessions allValues] valueForKey:@"connectedPeers"]; } 

发送数据到一个特定的同行或通过广播可以用这样的方法:

 - (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; } } 

你有没有尝试在应用程序closures之前断开连接? 这应该正确地从会话中删除对等,并清除为对等分配的任何资源。

具体来说,我的意思是像[self.peer disconnect] applicationWillTerminate:

我一直有类似的问题。 似乎如果我已经在一台iOS设备上运行我的应用程序,并连接到另一台,然后退出并重新启动(比如说,当我从Xcode重新运行时),那么我处于一种情况,在这种情况下,我得到一个Connected消息,然后是一个Not Connected稍后留言。 这是把我扔掉。 但仔细观察,我可以看到“未连接”消息实际上是指与已连接的不同peerId。

我认为这里的问题是,我所看到的大多数示例只关心peerID的displayName,忽略了可以为同一个device / displayName获取多个peerID的事实。

我现在先检查displayName,然后通过比较指针来validationpeerID是否相同。

 - (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)