【问题标题】:Why does Multi Peer Connectivity only work with MCAdvertiserAssistant and not MCNearbyServiceAdvertiser为什么 Multi Peer Connectivity 仅适用于 MCAdvertiserAssistant 而不是 MCNearbyServiceAdvertiser
【发布时间】:2014-11-14 22:45:29
【问题描述】:

我在MultiPeerConnectivity(MCF)上关注了这个tutorial并列出了大多数在线教程,他们采取了使用MCAdvertiserAssistantMCBrowserViewController服务的捷径

我尝试实现相同的教程,但改用 MCNearbyServiceAdvertiserMCNearbyServiceBrowser,因为我有兴趣在我的应用上自定义可发现性。

就列出附近的设备而言,一切都很好。但随后问题就出现在MCNearbyServiceAdvertiserDelegate 我称之为此方法的地方:

- (void)           advertiser:(MCNearbyServiceAdvertiser *)advertiser
 didReceiveInvitationFromPeer:(MCPeerID *)peerID
                  withContext:(NSData *)context
            invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {

    // Allow the peer to join this Vibereel
    MCSession *peerSession = [[MCSession alloc] initWithPeer:_peerID];
    peerSession.delegate = self;
    invitationHandler(YES, peerSession);
    NSLog(@"Accepted entry request for peer %@", [peerID displayName]);
}

不会触发did change state方法:

-(void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state

虽然它与原始版本一样。

我知道我显然需要添加更多代码来演示问题.. 所以我创建了一个以原始代码开头的github repo。这是commit,它添加了定制的浏览器和定制的 UITableViewController 以显示附近的设备(工作正常),这是做广告的commit不起作用

【问题讨论】:

  • 你能发布你发送邀请的代码吗?
  • 我遇到了同样的问题,最终通过将会话保存在实例变量中来摆脱它。它很奇怪,但很有效。

标签: ios objective-c cocoa bonjour multipeer-connectivity


【解决方案1】:

使 peerSession 成为类的属性,而不是方法的局部变量。问题是在您的代码中,peerSession 在方法结束时被释放。我的blog 上有一个工作示例。

【讨论】:

  • MCSession 实例被传递给invitationHandler 块,因此在方法中释放它并不重要。不过,我同意会话应该是一个属性。没有理由每次都创建一个新的。
  • Peter 的博客还指出,对于同时拥有广告商和浏览器的同行,不要接受双向会话,否则底层代码似乎会混淆。他选择比较 didReceiveInviation 中 peerID 的哈希值来决定两者中的哪一个应该接受,哪个应该拒绝。
【解决方案2】:

在查看您的代码库上的代码后,这里有几个想法,我确信这个问题主要与您设置 MCSession 对象的方式有关。我同意 Peter 的观点,您应该在整个流程中使用一个通用会话对象作为强参考。

其次,由于您尝试仅使用 MCNearbyServiceBrowserMCNearbyServiceAdvertiser 进行操作,因此您需要确保流程设置正确。通过以下回调找到对等点后,

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info;

现在在对等端使用[browser invitePeer:peerID toSession:self.session withContext:nil timeout:0]; 邀请对等点,您将收到以下委托的回调,

- (void) advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void(^)(BOOL accept, MCSession *session))invitationHandler

并且您通过确认invitationHandler(YES, session) 来接受邀请(正如您在上面所做的那样),如果您的会话对象在整个流程中是通用的,这应该得到- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state 触发MCSessionStateNotConnected 然后MCSessionStateConnecting 状态.现在,在第一个对等点上,您将收到以下委托回调

- (void)session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void(^)(BOOL accept))certificateHandler;

在这里您应该通过设置certificateHandler(YES) 来确认建立连接。这是最后一个非常重要的部分,特别是当您试图在没有工厂提供的视图控制器的情况下让整个事情正常工作时。

我知道第一次让它工作并不容易,但一路走来就很容易了。请在 cmets 中提及我,我会回复您以进行任何澄清。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-05
    • 2012-12-06
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多