2015-03-18 23 views
1

Я использую подход хоста/клиента к использованию возможностей MultiPeer Connectivity.Multipeer Connectivity kill session

Таким образом, когда пользователь его кнопка отключения

-(IBAction)disconnect:(id)sender { 

    [_appDelegate.mcManager.session disconnect]; 

    [_arrConnectedDevices removeAllObjects]; 



    ConnectionsViewController *game = [self.storyboard instantiateViewControllerWithIdentifier:@"ConnectionsViewController"]; 

    [self presentViewController:game animated:YES completion:nil]; 

} 

Теперь, это работает отлично. С точки зрения хостов он получает сообщение об отключении в журнале. и клиент переходит к новому контроллеру представления. И таблица обновляется. с этим.

-(void)peerDidChangeStateWithNotification:(NSNotification *)notification{ 
    MCPeerID *peerID = [[notification userInfo] objectForKey:@"peerID"]; 
    NSString *peerDisplayName = peerID.displayName; 
    MCSessionState state = [[[notification userInfo] objectForKey:@"state"] intValue]; 

    if (state != MCSessionStateConnecting) { 
     if (state == MCSessionStateConnected) { 
      if (_makeSureImHost) { 
       [_arrConnectedDevices addObject:peerDisplayName]; 

       [_tblConnectedDevices performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; 
      } 

      else { 
       [self sendMessageToHostWithMessage:@"deviceInfo"]; 
      } 
     } 
     else if (state == MCSessionStateNotConnected){ 
      if ([_arrConnectedDevices count] > 0) { 
       int indexOfPeer = (int)[_arrConnectedDevices indexOfObject:peerDisplayName]; 
       [_arrConnectedDevices removeObjectAtIndex:indexOfPeer]; 

       NSLog(@"%@ Disconnected", peerDisplayName); 

       [_tblConnectedDevices performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; 

       _tblConnectedDevices.frame = CGRectMake(_backgroundImage.frame.size.width/2 - 150, self.backgroundImage.frame.size.height/3, 300, 150); 


      } 
     } 
    } 
} 

КОНЕЦ LOBBY VIEW CONTROLLER

НАЧАЛО СВЯЗИ ЗРЕНИЯ УПРАВЛЕНИЯ

Когда клиент нажимает для просмотра локальных устройств это работает

- (IBAction)browseForDevices:(id)sender { 
    [UIView animateWithDuration:0.5f 
        animations:^{ 
         _searchButton.frame = CGRectMake(-100, self.backgroundImage.frame.size.height/2 + 60, 100, 35.0); 
         _hostButton.alpha = 0; 
         _modeLabel.alpha = 0; 
        }]; 

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     [[_appDelegate mcManager] setupPeerAndSessionWithDisplayName:[UIDevice currentDevice].name]; 
     [[_appDelegate mcManager] advertiseSelf:false]; 

     [[_appDelegate mcManager] setupMCBrowser]; 
     [[[_appDelegate mcManager] browser] setDelegate:self]; 
     _appDelegate.mcManager.browser.maximumNumberOfPeers = 1; 

     _appDelegate.mcManager.browser.modalTransitionStyle=UIModalTransitionStyleCrossDissolve; 
     [self presentViewController:[[_appDelegate mcManager] browser] animated:YES completion:nil]; 
    }); 

} 

Когда соединение установлен

-(void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController { 
    [_appDelegate.mcManager.browser dismissViewControllerAnimated:NO completion:^{ 
     [self launchViewController]; 
    }]; 
} 

-(void)launchViewController { 
    LobbyViewController *lobby = [self.storyboard instantiateViewControllerWithIdentifier:@"LobbyViewController"]; 
    [self presentViewController:lobby animated:NO completion:nil]; 
} 

Из этого

-(void)peerDidChangeStateWithNotification:(NSNotification *)notification { 
    MCPeerID *peerID = [[notification userInfo] objectForKey:@"peerID"]; 
    NSString *peerDisplayName = peerID.displayName; 
    MCSessionState state = [[[notification userInfo] objectForKey:@"state"] intValue]; 

    if (state != MCSessionStateConnecting) { 
     if (state == MCSessionStateConnected) { 
      [self browserViewControllerDidFinish:[[_appDelegate mcManager] browser]]; 

     } 
    } 
    else if (state == MCSessionStateNotConnected){ 
     if ([_arrConnectedDevices count] > 0) { 
      int indexOfPeer = (int)[_arrConnectedDevices indexOfObject:peerDisplayName]; 
      [_arrConnectedDevices removeObjectAtIndex:indexOfPeer]; 


     } 
    } 
} 

сейчас. Когда соединение выполняется в первый раз. Все это работает безупречно. Он подключается, загружает представление, хозяин запускает игру, игра отлично работает, и данные передаются отлично.

Однако, если вы отключитесь от лобби. Перейдите в диспетчер соединений соединений, затем снова найдите устройства. Он будет подключаться, однако диспетчер просмотра лобби будет NOT находиться в иерархии вида и закроет браузер и останется в контроллере вида соединения.

Затем, чтобы завершить его, соединение было выполнено. однако, когда он получает сообщение от хоста, он будет посылать ответ дважды или три раза или четыре, что приведет меня к тупику. Единственное, что я могу предположить, это то, что предыдущий сеанс запоминается как-то с точки зрения «клиентов».

Теперь шаги, которые я могу предпринять, чтобы избежать этого беспорядка. Если я убью приложение и перезапустите его, теперь я смогу подключиться снова с точки зрения клиентов. Это заставляет меня поверить, проблема заключается в конце клиента.

Моя проблема в том, что я должен абсолютно разбираться в этом. Таким образом, разъединение полностью удалит все из сеанса. Поэтому они могут снова подключиться. И не может полагаться на сообщение, чтобы сообщить пользователю перезапустить приложение. Этого просто не может быть.

Вот мой весь файл MCManager.m.

@implementation MCManager 

-(id)init{ 
    self = [super init]; 

    if (self) { 
     _peerID = nil; 
     _session = nil; 
     _browser = nil; 
     _advertiser = nil; 
    } 

    return self; 
} 

-(void)setupPeerAndSessionWithDisplayName:(NSString *)displayName{ 
    _peerID = [[MCPeerID alloc] initWithDisplayName:displayName]; 

    _session = [[MCSession alloc] initWithPeer:_peerID]; 
    _session.delegate = self; 
} 

-(void)setupMCBrowser{ 
    _browser = [[MCBrowserViewController alloc] initWithServiceType:@"chat-files" session:_session]; 
} 

-(void)advertiseSelf:(BOOL)shouldAdvertise{ 
    if (shouldAdvertise) { 
     _advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:@"chat-files" 
                  discoveryInfo:nil 
                   session:_session]; 
     [_advertiser start]; 
    } 
    else{ 
     [_advertiser stop]; 
     _advertiser = nil; 
    } 
} 

-(void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{ 
    NSDictionary *dict = @{@"peerID": peerID, 
          @"state" : [NSNumber numberWithInt:state] 
          }; 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"MCDidChangeStateNotification" 
                 object:nil 
                 userInfo:dict]; 
} 


-(void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{ 
    NSDictionary *dict = @{@"data": data, 
          @"peerID": peerID 
          }; 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"MCDidReceiveDataNotification" 
                 object:nil 
                 userInfo:dict]; 
} 


-(void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress{ 

} 


-(void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error{ 

} 


-(void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID{ 

} 

@end 

#import <MultipeerConnectivity/MultipeerConnectivity.h> 

@interface MCManager : NSObject <MCSessionDelegate> 

@property (nonatomic, strong) MCPeerID *peerID; 
@property (nonatomic, strong) MCSession *session; 
@property (nonatomic, strong) MCBrowserViewController *browser; 
@property (nonatomic, strong) MCAdvertiserAssistant *advertiser; 

-(void)setupPeerAndSessionWithDisplayName:(NSString *)displayName; 
-(void)setupMCBrowser; 
-(void)advertiseSelf:(BOOL)shouldAdvertise; 
@end 

Если кто-то знает, что я делаю неправильно, я был бы очень признателен. Это сводит меня с ума.

+0

Спасибо. Добавьте некоторый контекст для чтения чтения.Я пришел сюда, потому что мне было интересно, нужно ли мне вестибюль или подключение к одному другому устройству приводит к тому, что MPC отправляет связанное событие ко всем другим устройствам, уже подключенным к этому другому устройству? Что делает ваш код для меня, то есть зачем использовать хост/клиент? – bootchk

+0

@bootchk Этот вопрос был направлен на повторное подключение после отключения. Тем не менее, я думал, что упомянул бы, что я использую его в определенном шаблоне. Ваш вопрос о всех получаемых клиентах - нет. Если вы используете peerID для отправки сообщения этому конкретному клиенту, вы можете отправить сообщение только этому клиенту. Однако, как хозяин. Каждый получает клиент для размещения сообщений, которые легко интерпретировать с помощью простого логического. И причина использования хоста/клиента заключается в простоте матча/лобби. Где, в качестве альтернативы, вы оказываетесь в беспорядке, пытаясь понять это. – Daniel

ответ

1
[[NSNotificationCenter defaultCenter] removeObserver:name:object:]; 

Устранены все мои проблемы. Надеюсь, это поможет и другим людям.

Смежные вопросы