【问题标题】:Multipeer Connectivity: getting an invitation accepted (using built-in browser VC)Multipeer Connectivity:接受邀请(使用内置浏览器 VC)
【发布时间】:2013-10-01 18:25:49
【问题描述】:

我正在尝试follow the WWDC talk 了解 MultipeerConnectivity 框架。在多次错误启动后,浏览器会显示对等点,并发出邀请。

但是当我在对等设备上按“接受”时,浏览器不断显示“正在连接”。我认为MCBrowserViewController 负责处理逻辑,我可以放松,直到浏览器的用户按下取消或完成,并且委托方法被触发。我敢打赌,这很明显,但它让我无法理解。

这是我希望的相关代码。我在 AppDelegate 中有它。各种委托方法中的 NSLog 语句都会按我的预期被调用——当然,browserViewControllerDidFinish: 中的语句除外。

请记住,浏览器和邀请确实会出现,所以某事是对的!

在@interface...

@property   (strong, nonatomic) MCSession   *theSession;
@property   (strong, nonatomic) MCAdvertiserAssistant       *assistant;
@property   (strong, nonatomic) MCBrowserViewController     *browserVC;

在@实现中

static    NSString* const    kServiceType = @"eeps-multi";

// called from viewDidAppear in the main ViewController

-(void)     startSession
{
    if (!self.theSession) {
        UIDevice *thisDevice = [UIDevice currentDevice];

        MCPeerID *aPeerID = [[ MCPeerID alloc ] initWithDisplayName: thisDevice.name];
        self.theSession = [[ MCSession alloc ] initWithPeer: aPeerID ];
        self.theSession.delegate = self;
    } else {
        NSLog(@"Session init skipped -- already exists");
    }
}

// called from viewDidAppear in the main ViewController

- (void)    startAdvertising
    {
    if (!self.assistant) {
        self.assistant = [[MCAdvertiserAssistant alloc] initWithServiceType:kServiceType
                                                              discoveryInfo:nil
                                                                    session:self.theSession ];
        self.assistant.delegate = self;
        [ self.assistant start ];
    } else {
        NSLog(@"Advertiser init skipped -- already exists");
    }
}

// called from the main ViewController in response to a button press

- (void)    startBrowsing
{
    if (!self.browserVC){
        self.browserVC = [[MCBrowserViewController alloc] initWithServiceType:kServiceType 
                                                                      session:self.theSession];
        self.browserVC.delegate = self;
    } else {
        NSLog(@"Browser VC init skipped -- already exists");
    }

    [ self.window.rootViewController presentViewController:self.browserVC animated:YES completion:nil];
}

提前致谢!

【问题讨论】:

    标签: cocoa-touch ios7 invitation multipeer-connectivity


    【解决方案1】:

    感谢评论者提出的出色建议,这些建议让我发现了自己的错误。这里是:

    如果你实现了MCSessionDelegate方法session:didReceiveCertificate:fromPeer:certificateHandler方法,它会拦截peer连接会话的尝试。您应该在该方法中明确批准该连接或将其注释掉。

    细节和经验教训:

    除了我展示的代码之外,我还对各种委托方法进行了粗略的实现。一种MCSessionDelegate方法就是这个:

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

    扩展上述@Big-O Claire 的建议,我开始关注所有这些委托方法,以防万一。当对等方点击 AdvertiserAssistant UI 中的“接受”按钮时,就会触发此事件。

    此方法使您有机会确定对等方是否合法,如果您不想连接(使用certificateHandler:),则不连接。苹果说,

    您的应用应检查附近对等方的证书,然后应决定是否信任该证书。做出决定后,您的应用应调用提供的 certificateHandler 块,传递 YES(以信任附近的对等方)或 NO(以拒绝它)。

    此外,您还可以得到以下提示:

    重要提示:多点连接框架不会尝试以任何方式验证点提供的身份或证书。如果您的委托未实现此方法,则会自动接受所有证书。

    当我注释掉这个方法时,连接就完成了——至少这个问题得到了解决。

    【讨论】:

    • 非常感谢,这让我免于调试数小时。我只是把所有委托方法都扔在那里以便以后实现它们,甚至不知道 didReceiveCertificate。
    【解决方案2】:

    我遇到了同样的问题,结果我为浏览器和广告商使用了相同的会话。拆分会话,但确保 serviceType 是相同的,它会像一个魅力一样工作

    - (void) setUpMultipeer{
        //  Setup Peer ID
        self.myPeerID = [[MCPeerID alloc] initWithDisplayName:[UIDevice currentDevice].name];
    
        //  Setup Sessions
        self.advertiseSession = [[MCSession alloc] initWithPeer:self.myPeerID];
        self.advertiseSession.delegate = self;
    
        self.browserSession = [[MCSession alloc] initWithPeer:self.myPeerID];
        self.browserSession.delegate = self;
    
    
        //  Setup BrowserVC
        self.browserVC = [[MCBrowserViewController alloc] initWithServiceType:@"SERVICE_TYPE" session:self.browserSession];
        self.browserVC.delegate = self;
    
        //  Setup Advertiser
        self.advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:@"SERVICE_TYPE" discoveryInfo:nil session:self.advertiseSession];
        [self.advertiser start];
    }
    

    【讨论】:

    • 谢谢!尝试了它并没有用,但帮助我找到了实际问题(如下)。一旦发现工作正常,我就回去尝试了一个会话,到目前为止它运行良好。当然,我仍然刚刚开始发现工作,所以我可能很快需要你的建议。随着事情的进展,我会提交一份报告。 :)
    • 这个对我有用,正在使用appcoda 的教程,它使用相同的会话进行广告和交流,“完成”按钮从未触发。
    【解决方案3】:

    在使用新的 MC 框架时,我自己并没有走 MCBrowserViewController 路线,但是从 WWDC 演示文稿的幻灯片 51 中,看起来确实只有当用户按下完成时才会调用 browserViewControllerDidFinish:。因此,如果您的对等方仍显示为“正在连接...”,则此回调可能不是问题所在。

    我想知道您是否必须手动将您的对等连接到会话。您已经设置了MCSession 委托,所以我假设您正在实施session:peer:didChangeState。设置断点并观察MCSessionState 何时为MCSessionStateConnected。我唯一不确定的是,您是否需要在广告商端、浏览器端或两者都手动处理此问题。如果您能弄清楚框架在哪一步停止处理它,那将很有帮助。

    【讨论】:

    • 好主意,所以更新一下:当我更仔细地观看更多代表电话时(并在下面实施@Alla 的建议),我看到didChangeState 未连接 当设备拒绝连接,但接受连接时没有变化。所以我仍然感到困惑(并且仍在寻找)。欢迎提出任何建议!
    • 我也在这一点上,我的方法是设置一个名为 currentSession 的静态可选。在游戏中我引用这个对象来发送数据包。这样,当会话报告未连接时,我可以将其设置为 nil,并且游戏可以优雅地处理网络连接失败。这样我就不会直接引用浏览器会话或广告会话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多