Я использую подход хоста/клиента к использованию возможностей 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
Если кто-то знает, что я делаю неправильно, я был бы очень признателен. Это сводит меня с ума.
Спасибо. Добавьте некоторый контекст для чтения чтения.Я пришел сюда, потому что мне было интересно, нужно ли мне вестибюль или подключение к одному другому устройству приводит к тому, что MPC отправляет связанное событие ко всем другим устройствам, уже подключенным к этому другому устройству? Что делает ваш код для меня, то есть зачем использовать хост/клиент? – bootchk
@bootchk Этот вопрос был направлен на повторное подключение после отключения. Тем не менее, я думал, что упомянул бы, что я использую его в определенном шаблоне. Ваш вопрос о всех получаемых клиентах - нет. Если вы используете peerID для отправки сообщения этому конкретному клиенту, вы можете отправить сообщение только этому клиенту. Однако, как хозяин. Каждый получает клиент для размещения сообщений, которые легко интерпретировать с помощью простого логического. И причина использования хоста/клиента заключается в простоте матча/лобби. Где, в качестве альтернативы, вы оказываетесь в беспорядке, пытаясь понять это. – Daniel