2015-03-18 1 views
1

J'utilise une approche hôte/client pour utiliser MultiPeer Connectivity.Session d'arrêt de la connectivité Multipeer

Ainsi, lorsqu'un utilisateur lui sur le bouton de déconnexion

-(IBAction)disconnect:(id)sender { 

    [_appDelegate.mcManager.session disconnect]; 

    [_arrConnectedDevices removeAllObjects]; 



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

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

} 

Maintenant, cela fonctionne très bien. Du point de vue des hôtes, il reçoit un message de déconnexion dans le journal. et le client se déplace vers le nouveau contrôleur de vue. Et la table est mise à jour. avec ça.

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


      } 
     } 
    } 
} 

FIN DE LOBBY VIEW CONTROLLER

DÉBUT DE CONNEXION VUE DE COMMANDE

Lorsqu'un client appuie pour rechercher des périphériques locaux ce court

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

} 

Lorsqu'une connexion est établi

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

De cette

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


     } 
    } 
} 

maintenant. Quand une connexion est établie pour la première fois. Tout cela fonctionne parfaitement. Il se connecte, charge la vue, l'hôte démarre le jeu, le jeu fonctionne correctement et les données sont parfaitement transférées.

Cependant, si vous vous déconnectez du lobby. Placez-vous dans le viewcontroller de connexion, puis recherchez de nouveau les périphériques. Il se connectera, mais le contrôleur de vue du hall ne sera pas dans la hiérarchie de vue et fermera le navigateur et restera dans le contrôleur de vue de connexion.

Ensuite, pour couronner le tout, la connexion a été établie. Pourtant, quand il reçoit un message de l'hôte, il enverra la réponse, deux fois ... ou trois fois, ou quatre, me conduisant à une impasse. La seule chose que je puisse présumer est que l'on se souvient de la session précédente d'une certaine manière du point de vue des "clients". Maintenant, les mesures que je peux prendre pour éviter ce désordre. Si je tue l'application et la relance, je peux maintenant me reconnecter du point de vue des clients. Ce qui me porte à croire, le problème est sur la fin des clients.

Mon problème est que je dois absolument régler cela. Donc, une déconnexion supprimera complètement tout de la session. Donc, ils peuvent se reconnecter à nouveau. Et ne peut pas compter sur un message pour dire à l'utilisateur de redémarrer leur application. Ça ne peut pas l'être.

Voici mon fichier MCManager.m entier.

@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 

Si quelqu'un sait ce que je fais mal, j'apprécierais beaucoup. Ça me rend dingue.

+0

Merci. Veuillez ajouter un contexte pour les lecteurs de nieve.Je suis arrivé ici parce que je me demandais si j'avais besoin d'un lobby, ou est-ce que la connexion à un autre périphérique fait que MPC envoie un événement connecté à tous les autres périphériques déjà connectés à cet autre périphérique? Que fait votre code pour moi, c'est-à-dire pourquoi utiliser l'hôte/le client? – bootchk

+0

@bootchk Cette question visait la reconnexion après une déconnexion. Cependant, j'ai pensé que je mentionnerais que je l'emploie dans un modèle particulier. Votre question sur tous les clients recevant est non. Si vous utilisez l'ID homologue pour envoyer un message à ce client particulier, vous pouvez envoyer un message à ce client uniquement. Cependant, en tant qu'hôte. Tout le monde reçoit le client pour héberger des messages, ce qui peut facilement être interprété avec un simple booléen. Et la raison d'utiliser un hôte/client est pour la simplicité d'un match/lobby. Où, alternativement, vous finissez dans un gâchis en essayant de le comprendre. – Daniel

Répondre

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

A résolu tous mes problèmes. J'espère aider d'autres personnes aussi.