首页 > 解决方案 > 多点连接:在 Objective-C++ 中的浏览无声无息地失败

问题描述

我正在尝试为 Objective-C++ 中的 Multipeer Connectivity 应用程序编写浏览器/发现端。我想我可以做广告,据我所知,因为我可以使用 Discovery ( https://itunes.apple.com/us/app/discovery-dns-sd-browser/id1381004916?mt=12 ) 看到它。但是我的浏览器什么也没看到。我究竟做错了什么?

#include <iostream>
#include <thread>

#import <MultipeerConnectivity/MultipeerConnectivity.h>

@interface Bowser : NSObject<MCNearbyServiceBrowserDelegate>

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

- (void)browser:(MCNearbyServiceBrowser *)browser 
    lostPeer:(MCPeerID *)peerID;

@end

@implementation Bowser

- (void)browser:(MCNearbyServiceBrowser *)browser 
    foundPeer:(MCPeerID *)peerID 
    withDiscoveryInfo:(NSDictionary *)info {
    std::cout << "Hello" << std::endl;
}

- (void)browser:(MCNearbyServiceBrowser *)browser 
    lostPeer:(MCPeerID *)peerID {
    std::cout << "Goodbye" << std::endl;
}

@end

int main() {
    MCPeerID* peerid = [[MCPeerID alloc] initWithDisplayName:@"PeerId"];
    Bowser* delegate = [[Bowser alloc] init];

    MCNearbyServiceBrowser* browser = [MCNearbyServiceBrowser alloc];
    [browser initWithPeer:peerid serviceType:@"m"];

    browser.delegate = delegate;

    [browser startBrowsingForPeers];

    using namespace std::chrono_literals;
    std::this_thread::sleep_for(10s);

    [browser stopBrowsingForPeers];
}

关于如何调试正在发生的事情的建议也很有用。有人……?

标签: macosobjective-c++multipeer-connectivity

解决方案


我终于想通了。MultipeerConnectivity 需要一个运行循环。这不在文档中。

我假设 MultipeerConnectivity API 在方法调用时创建了它所需的线程和/或循环[browser startBrowsingForPeers]。它不是。

此代码中没有任何地方启动运行循环。此外,有趣的是,直接使用 NSThread 不会启动运行循环,即使它暗示它会

您的应用程序既不创建也不显式管理 NSRunLoop 对象。每个 NSThread 对象(包括应用程序的主线程)都有一个根据需要自动为其创建的 NSRunLoop 对象。如果您需要访问当前线程的运行循环,请使用类方法 currentRunLoop。

将创建一个运行循环(并启动它)的是CFRunLoopRun()

当前线程的运行循环在默认模式下运行(请参阅默认运行循环模式),直到使用 CFRunLoopStop 停止运行循环或从默认运行循环模式中删除所有源和计时器。

那么,什么会阻止它CFRunLoopStop(CFRunLoopRef rl)

该函数强制 rl 停止运行并将控制权返回给调用 CFRunLoopRun 或 CFRunLoopRunInMode 以激活当前运行循环的函数。

当然,CFRunLoopStop需要 aCFRunLoopRef作为论据。您可以通过使用 来获得它CFRunLoopGetCurrent,只要记住它是一个参考并且可能随时过期。我认为您可以非常确定当您在运行循环中运行的回调中时,运行循环不会死掉。但我不会指望它之后会继续存在。实际上,在这种情况下,重点是在这一点上杀死它;所以我希望它会消失。


推荐阅读