I'm working on a game that uses NWBrowser
and NWListener
to create a connection between an iOS and tvOS app.
I've got the initial networking up and running and it works perfectly when running in the simulator(s). However, when I run on-device(s), I've found that browseResultsChangedHandler
gets called multiple times for what is ostensibly the same service.
My browser handler (which runs on iOS) looks like this:
browser.browseResultsChangedHandler = { [weak self] results, changes in
if let result = browser.browseResults.first {
self?.onPeerConnected?(PeerConnection(endpoint: result.endpoint))
}
}
The first time it gets called, the interface in the NWBrowser.Result
is en0
, but the 2nd time it gets called, it is en0
AND awdl0
.
Because my current handling is so naive, this re-invocation ends up with two connections being made to the remote server (the Apple TV).
Now, I know that this handler, by its very name, is designed to be called multiple times as things change, so I'm curious as to what strategies I might employ here.
Is there any value in tearing down any previous connections and re-connecting using the latest one? Should I just kill the browser as soon as I handle the first one? Just ignore subsequent ones?
I'm sure that, to a degree, the answer is probably "it depends"... but I'm curious to see if there might be at least some high-level strategies like "whatever you do, don't do xxxx" or "most apps do yyyy" :-)
Thanks.
Yeah, that’s quite reasonable. en0
is likely your infrastructure Wi-Fi interface whereas awdl0
is a peer-to-peer Wi-Fi interface.
IMPORTANT BSD interface names, like en0
, are not considered API, so you shouldn’t rely on them in your code. However, it’s helpful to know what to expect when you’re debugging.
My general advice is that you not connect on discovery. Rather, show the user a list and allow them to choose. That’ll help with this problem because the list is likely to have stabilised before the user makes a choice.
However, I understand that this model doesn’t work for everyone. And, even if you follow the model, it’s still possible for new browse results to come in while you’re connecting.
As to what you do about that, well… you guess it… it depends (-: You have a bunch of options:
-
‘Debounce’ the browser results, so you only start your connection once things have been stable for a bit.
-
Start an immediate connection and then, if it fails to go through quickly, cancel it and start a new connection with the additional results.
-
Start multiple connections and let them race.
-
Combine the above, so start an immediate connection and, if it it doesn’t through promptly, start the additional ones and then use whichever one connects first.
-
Probably more that I’ve not thought of.
And how do you choose between these? Well, one obvious factor is complexity. The other factor I’d consider is real world behaviour. That’s especially important with peer-to-peer Wi-Fi, which has significant limitations in practice.
Oh, and as you’re combining iOS and tvsOS, I wanted to make sure you’re aware of DeviceDiscoveryUI framework.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"