Multipeer Connectivity kill会话

时间:2015-03-18 00:40:22

标签: ios objective-c session multipeer-connectivity

我使用主机/客户端方法来使用MultiPeer连接。

因此,当用户使用断开连接按钮时

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

如果有人知道我做错了什么,我会非常感激。这让我疯了。

2 个答案:

答案 0 :(得分:1)

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

修复了我的所有问题。希望能帮助其他人。

答案 1 :(得分:0)

使用Swift,我可以如下结束多人会话(在完成对会话跟踪器的deinit的检查之后):

func stopSession() {
        self.serviceBrowser.stopBrowsingForPeers()
        self.serviceBrowser.delegate = nil
        
        self.serviceAdvertiser.stopAdvertisingPeer()
        self.serviceAdvertiser.delegate = nil

        self.session.disconnect()
        self.peerSessionIDs.removeAll()
        self.session.delegate = nil
        self.session = nil

        self.multipeerConnectivityService = nil
        self.serviceType = nil
    }

换句话说,已注册和初始化程序的所有内容都将被取消初始化。我是按照相反的顺序进行的,但是我不确定这里的顺序是否重要。