Как MCNearbyServiceBrowser узнает, отклонил ли MCNearbyServiceAdvertiser приглашение?

Вопрос о многопользовательском подключении iOS...

Если MCNearbyServiceAdvertiser отклоняет приглашение от MCNearbyServiceBrowser по телефону:

invitationHandler(NO, nil);

...in:

advertiser:didReceiveInvitationFromPeer:withContext:invitationHandler:

...может ли MCNearbyServiceBrowser узнать, что приглашение было отклонено?

Я вижу, что устройство, использующее MCNearbyServiceBrowser, получает изменение состояния сеанса на MCSessionStateNotConnected, когда рекламодатель отклоняет приглашение, но я полагаю, что просматривающее устройство может получить MCSessionStateNotConnected и по другим причинам... например, устройство рекламодателя уходит (отключается , и т.д).

Любые предложения о том, как отличить отклоненное приглашение от другого вида отключения?

Спасибо.

-Аллан


person lagouyn    schedule 29.06.2014    source источник


Ответы (1)


Согласно документам, 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
comment
Спасибо за ваш ответ, Крис. Я собираюсь потратить некоторое время на его рассмотрение и тестирование. Отвечу снова. - person lagouyn; 07.07.2014
comment
@lagouyn это сработало для вас? Собирался применить аналогичный совет к другому вопросу, если это так... - person ChrisH; 25.07.2014