MultiPeerConnectivity under iOS 14

Hey,

I have an app I've been experimenting with on iOS 13 that uses MultiPeerConnectivity. After upgrading to iOS 14 on one of my devices and using Xcode 12 this app no longer works. As outlined in "Support local network privacy in your app" I've added a description with NSLocalNetworkUsageDescription in Info.plist. Since the app uses Bonjour advertisting and browsing via MCNearbyServiceAdvertiser and MCNearbyServiceBrowser I've also added the service name via NSBonjourServices to Info.plist. It's my understanding that this should be enough to make browsing and advertising work.

What I am observing is that when I call startAdvertisingPeer on my instance of MCNearbyServiceAdvertiser I am not seeing the local network permission prompt instead I see the following error in the console.

Code Block
2020-06-27 13:26:54.634264+0100 MultiPeerTest[18970:1571288] [MCNearbyServiceAdvertiser] Server did not publish: errorDict [{
NSNetServicesErrorCode = "-72000";
NSNetServicesErrorDomain = 10;
}].


Further my app is not showing up under Settings > Privacy > Local Network on my iPadOS 14 device.

I looked at the TicTacToe example which declares the bonjour service _tictactoe._tcp as its Bonjour Service but this seems to violate the Bonjour specification for service type as described in the documentation for MCNearbyServiceAdvertiser.

My code is roughly

Code Block swift
localPeer = MCPeerID.init(displayName: deviceName)
advertiser = MCNearbyServiceAdvertiser(
peer: localPeer,
discoveryInfo: [:],
serviceType: "my-service"
)
browser = MCNearbyServiceBrowser(
peer: localPeer,
serviceType: "my-service"
)
browser.startBrowsingForPeers()
advertiser.startAdvertisingPeer()


Environment:
  • Xcode 12 Beta(12A6159)

  • iPad Pro(10.5", 2017) running iPadOS 14.0 Beta


Replies

I figured it out(at least partially). The service type you declare when creating an MCNearbyServiceAdvertiser is used by MultiPeerConnectivity to generate the actualy Bonjour service so if you have the service type my-service declaring _my-service_.tcp in Info.plist as a Bonjour Service solves the issue.

With this change at least it works as expected, i.e. the prompt shows up and the device can discover other devices, however it's not clear if _{service}_.tcp is enough? Given that MultiPeerConnectivity is a high level framework do I also need to declare _{service}_.udp and others in Info.plist?

it's not clear if _{service}_.tcp is enough?

Indeed. I think it is but I don’t know MultipeerConnectivity well enough to say that with 100% certainty. I think you should continue on your current path but also file a bug against the docs for clarification.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
  • it appears the underbars need to be different : format it like this:

    _{service}._tcp

    Then I see the modal '*** would like to find and connect to devices on your local network.

  • I discovered this by setting a breakpoint in MCNearbyServiceBrowserDelegate.browser(_:foundPeer:withDiscoveryInfo:)

    and looking at the browser's _formattedServiceType value, which looked like this:

    _serviceType __NSCFString * "WinGame" 0x0000000123456789 _formattedServiceType __NSCFString * "_WinGame._tcp" 0x000000012345678a

Add a Comment
The new MultipeerConnectivity documentation describes a new usage string that you need in your Info.plist file:

Apps that use the local network must provide a usage string in their Info.plist with the key NSLocalNetworkUsageDescription. Apps that use Bonjour must also declare the services they browse, using the NSBonjourServices key.

You can find a description of the key here:

https://developer.apple.com/documentation/bundleresources/information_property_list/nslocalnetworkusagedescription?changes=latest_major
Ignore...
Encountered the same issue and eventually solved it by
  1. Defining my unique ServiceType in the PeerToPeer handler (peertrack is fictional, use your own Type)

#define kMCSessionServiceType @“peertrack”

2. Making the following .plist entries:

Code Block
<key>NSLocalNetworkUsageDescription</key>
<string>Exchange data with nearby devices running the PeerTrack app.</string>
<key>NSBonjourServices</key>
<array>
<string>_peertrack._tcp</string>
</array>

3. Executing the Service Advertiser and Service Browser (pseudo code)
.
.
Code Block
[MCNearbyServiceAdvertiser alloc] initWithPeer:localPeerID discoveryInfo:nil serviceType:kMCSessionServiceType];
.
.
and
.
.
Code Block
[[MCNearbyServiceBrowser alloc] initWithPeer:localPeerID serviceType:kMCSessionServiceType];


4. Compiled app with Xcode 12.0 beta and Xcode 11.5.
Successfully tested the code on multiple iPhone, iPad, and simulator devices, running iOS 9.0, iOS 13.5, and iOS 14.0 beta.

Code Block
NOTE the leading underscore (_) character in the .plist NSBonjourServices definition entry. Test failed without the leading underscore character, although not included in the kMCSessionServiceType used by MCNearbyServiceAdvertiser and MCNearbyServiceBrowser.


Hope that this is helpful to someone by cutting down on debug time.

For me,  DJHarter's solution worked! Thank you so much.
Thanks @DJHarter.

FYI to others - I required both
Code Block swift
_{service}._tcp
&
Code Block swift
_{service}._udp

in my Info.plist.
How do we know the user denied access to Local Networks access?

How do we know the user denied access to Local Networks access?

Have you implemented -advertiser:didNotStartAdvertisingPeer:? Did that get called with an error?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
It also looks like MCBrowserViewController is unsupported on iOS 14. If I try to use it, I get

Code Block
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle <...> (loaded)' with name 'MCBrowserViewController''


It sounds like you must use MCNearbyServiceBrowser instead.
Be aware that Multipeer Connectivity uses Bonjour and thus you must both NSLocalNetworkUsageDescription and NSBonjourServices in your Info.plist. With regards the latter, Matt posted some great advice on that topic earlier today.

It also looks like MCBrowserViewController is unsupported on iOS 14.

It’s not meant to do that. If you fix your Info.plist and the problem persists, I’d appreciate you filing a bug about it. Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"