iPhone/iPod Touch 上的 Bonjour/NSNetServiceBrowser 将利用 Wifi 和蓝牙进行服务发现——至少在受支持的设备上是这样。每次您开始浏览服务时,它都会搜索 WiFi 和蓝牙(您可以在 iPhone 的控制台中的 Organizer 中进行验证)。由于您的模拟器“设备”无法使用蓝牙,您的 iPhone 会通过 WiFi 发现它。但是,如果您使用 NSNetService 在您的 iPhone 上发布,那么您也将通过 WiFi 和 蓝牙发布(如果支持并启用)。 NSNetServiceBrowser 在支持 BT 的硬件上运行时,将尽职尽责地找到这两个实例,并通过委托回调报告这两个实例。
蓝牙 PAN 设置比通过 Wifi 发布需要更长的时间,因此在发现并解决所有基于 Wifi 的服务后,BT 发现的服务通常会很好地显示出来。在测试两个真实设备时,我什至看到这两个服务都显示在我的 UI 中(通常仅在另一部手机崩溃之后)。
不过,这确实会导致一些令人沮丧的编码。您最好的选择是使用 netService:didNotResolve: (i) 重试解析,或 (ii) 使 netService 实例无效并等待另一部手机重新启动他们的应用程序。
此外,还有一些其他方面可能会出错。由于提供给您的 NSNetService 实例是自动释放的,因此您需要保留它。大多数人将它添加到 NSMutableArray 或 NSMutableDictionary。如果是这种情况,请确保在添加对象之前已正确初始化它。由于发送到 nil 的消息完全没问题,如果您将 addObject: 发送到 nil,它看起来好像一切正常。除了它不是。这在 Bonjour 故障排除中经常出现,并且发生在我们最好的人身上。确保您的 NSNetService 被安排到一个主动运行的运行循环中,并且以默认或通用模式运行。
Apple 提交了一个未解决的错误(截至 2009 年 10 月 4 日),因此每隔一段时间,Bonjour 更新不会导致委托方法被触发。我只在 3GS 上观察到这种情况。结果是客户端应用程序与网络不同步。
NSNetServiceBrowser 应该在服务离开网络时持续通知(在标称条件下)。上面的错误只是一个间歇性的,显然是特定于硬件的。如果您看到它始终如一地发生,那么您的应用程序很可能正在引发异常。如果您正在使用后台线程,则可能会发生这种情况而不会导致整个应用程序崩溃。您可能需要检查您的 iPhone 控制台和日志中的错误消息。确保已在符号 objc_exception_throw 上设置断点。
这是另一个我发现非常宝贵的故障排除技巧。使用以下命令通过终端监控开发机器上的 Bonjour 广播:dns-sd -B _serviceName。这将让您看到本地网络上为您提供服务的所有来来往往。如果您的应用退出,但 dns-sd 未显示 Remove 事件,则您的代码需要重新访问。如果 dns-sd 显示删除事件,但您的其他应用程序没有正确处理它,您可能会看到上述错误。也可能是您的代码没有做您认为它正在做的事情。请记住,这只会帮助您对 Wifi 到 Wifi 服务 Bonjour 进行故障排除。 iPhone 模拟器不支持蓝牙到蓝牙。
在我的开发博客上阅读完整的文章 Troubleshooting Bonjour Networking for the iPhone。