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 模拟器不支持蓝牙到蓝牙。
阅读我的开发博客上的完整文章,iPhone 的 Bonjour 网络故障排除。