Согласно документам, MCSessionStateNotConnected
может означать, что
"...близлежащий узел отклонил приглашение, соединение не может быть установлено, или ранее подключенный узел больше не подключен."
Вы не говорите в своем вопросе, что может привести к отклонению приглашения, но предполагая, что оно управляется пользователем, один из подходов может заключаться в том, чтобы ваш MCNearbyServiceAdvertiserDelegate
автоматически принимал приглашения, создавал новый сеанс для каждого однорангового узла, а затем представлял пользователя с выбором принятия или отклонения соединения. Ваши одноранговые узлы не будут считаться действительно сеансами друг с другом, пока они не получат последующее сообщение, указывающее на решение пользователя:
Таким образом, в вашем классе MCNearbyServiceAdvertiserDelegate
вы должны принять, а затем предложить пользователю:
- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser
didReceiveInvitationFromPeer:(MCPeerID *)peerID
withContext:(NSData *)context
invitationHandler:(void(^)(BOOL accept, MCSession *session))invitationHandler {
//Automatically accept with a new session
MCSession *newSession = [[MCSession alloc] initWithPeer:_myPeerID];
newSession.delegate = self;
//Keep track of the pending sessions in a mutable dictionary
_pendingSessionPeerIDMap[peerID.displayName] = newSession;
invitationHandler(YES,newSession);
/* Code here to present user with option to accept or decline peer */
}
И затем, когда пользователь ответил, у вас может быть метод, который отправляет простую строку как NSData, содержащую статус:
@property NSData *inviteAcceptedMsgData = [@"MPCInviteYES" dataUsingEncoding:NSUTF8StringEncoding];
@property NSData *inviteDeclinedMsgData = [@"MPCInviteNO" dataUsingEncoding:NSUTF8StringEncoding];
- (void)invitationFromPeerID:(MCPeerID *)peerID receivedResponse:(BOOL)accepted {
//Send a message to the peer that sent the invitation indicating whether the
//user accepted or declined
NSData *msgData = (accepted) ? _inviteAcceptedMsgData : _inviteDeclinedMsgData;
MCSession *peerSession = _pendingSessionPeerIDMap[peerID.displayName];
[peerSession sendData:msgData
toPeers:@[peerID]
withMode:MCSessionSendDataReliable
error:nil];
//Remove the pending session
[_pendingSessionPeerIDMap removeObjectForKey:peerID.displayName];
//And if the connection was accepted by the user, add to an accepted dictionary
_acceptedSessionPeerIDMap[peerID.displayName] = peerSession;
}
MCNearbyServiceBrowserDelegate
будет работать аналогичным образом:
- (void)browser:(MCNearbyServiceBrowser *)browser
foundPeer:(MCPeerID *)peerID
withDiscoveryInfo:(NSDictionary *)info {
//Send the invitation with a new session
MCSession *newSession = [[MCSession alloc] initWithPeer:_myPeerID];
newSession.delegate = self;
[browser invitePeer:peerID
toSession:newSession
withContext:nil
timeOut:0];
}
Затем браузер будет ждать сообщения от приглашенного им партнера, чтобы определить, действительно ли приглашение было принято:
- (void)session:(MCSession *)session
didReceiveData:(NSData *)data
fromPeer:(MCPeerID *)peerID {
//Check the data to see whether invite was accepted
if ([data isEqualToData:_inviteAcceptedMsgData]) {
//Add to an accepted dictionary
_acceptedSessionPeerIDMap[peerID.displayName] = session;
}
else if ([data isEqualToData:_inviteAcceptedMsgData]){
//Disconnect the session
[session disconnect];
}
}
Возможно, у вас уже есть система обмена сообщениями, но она представляет собой простую реализацию передачи состояния между подключенными узлами. Что касается отправки широковещательных сообщений или отображения подключенных пиров, _acceptedSessionPeerIDMap
следует использовать как истинную коллекцию пиров.
person
ChrisH
schedule
03.07.2014