我第一次使用mutlipeer连接框架,我想要编程(而不是助手类)控制。
当我在两个单独的设备上运行我的代码时,一切都正常工作,直到'广告客户'收到委托回调为止:
浏览客户端的委托回调在发现广告商时被调用:
-(void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info{
[[[UIAlertView alloc] initWithTitle:@"Peer Found" message:peerID.displayName delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show];
_session = [[MCSession alloc] initWithPeer:_myPeerID];
_session.delegate = self;
//connect to the discovered peer.
[_browser invitePeer:peerID toSession:_session withContext:nil timeout:30.0];
[_browser stopBrowsingForPeers];
}
然后,广告客户端的委托回调在收到邀请时被调用:
-(void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler{
//when my code runs, everything looks correct here.
//eg. peerID is definitely my 'browser' client's display name etc.
_session = [[MCSession alloc] initWithPeer:_myPeerID];
_session.delegate = self;
//using a simple version for testing... accept all invites.
invitationHandler(YES, _session);
//stop advertising now.
[_advertiser stopAdvertisingPeer];
}
在调用'invitationHandler(YES,_session)'之后,似乎永远不会在'浏览'客户端和'广告'客户端之间建立连接。
我在任一客户端设备上的MCSession对象上都没有收到任何委托回调(我收到一次或两次MCSessionStateNotConnected)。我原本以为我会收到MCSession委托回调:
-(void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state;
我错过了什么吗?还有其他人遇到过这个问题吗?
答案 0 :(得分:9)
Apple显然有一个错误。
这导致了这一发现:Why does my MCSession peer disconnect randomly?
您必须实现以下委托回调,即使它在docs ...
中列为可选项- (void) session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler
{
certificateHandler(YES);
}
答案 1 :(得分:1)
" didReceiveCertificate"委托方法是可选的,如果你不实现它,框架将假定你接受证书(注意证书可以是零)。
但是,如果您实现该方法然后将其保留为空,那么,确定,对等方将无法连接,因为框架将期望您使用YES或NO调用certificateHandler。
答案 2 :(得分:1)
我一直有类似的问题。看来,如果我在一台iOS设备上运行我的应用程序,并连接到另一台设备,然后退出并重新启动(比如当我从Xcode重新运行时),那么我处于一种情况下,我收到一条已连接的消息,然后是一台未连接的消息稍后。这让我失望了。但仔细观察,我可以看到Not Connected消息实际上是针对与已连接的消息不同的peerId。
我认为这里的问题是我见过的大多数样本只关心peerID的displayName,而忽略了你可以为同一个device / displayName获得多个peerID的事实。
我现在首先检查displayName,然后通过比较指针来验证peerID是否相同。
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state {
MyPlayer *player = _players[peerID.displayName];
if ((state == MCSessionStateNotConnected) &&
(peerID != player.peerID)) {
NSLog(@"remnant connection drop");
return; // note that I don't care if player is nil, since I don't want to
// add a dictionary object for a Not Connecting peer.
}
if (player == nil) {
player = [MyPlayer init];
player.peerID = peerID;
_players[peerID.displayName] = player;
}
player.state = state;
...
答案 3 :(得分:0)
我发现的另一个问题(也在其他示例代码中,即PeerKit)是在InvitationHandler(YES)之后的stopAdvertisingPeer可能是错误的。因为即使您接受邀请,也无法保证您将被连接。我认为最好只在连接时停止广告节目。