I am using NWBrowser to detect SignalK servers on a network using the following Swift code:
let browser = NWBrowser(for: .bonjourWithTXTRecord(type: "_http._tcp", domain: nil), using: NWParameters())
browser.browseResultsChangedHandler = { results, changes in
print("Found \(results.count) results and \(changes.count) changes")
}
When this is run on a network with 5 devices then the output is often
Found 5 results and 5 changes
But, sometime it is:
Found 2 results and 2 changes
Found 5 results and 3 changes
indicating that the browseResultsChangedHandler is being called more than once.
So my question is how do I determine when the browsing process has finished (obviously without the knowledge that there are 5 devices)?
The depreciated NetServiceBrowser had a delegate method (netServiceBrowser(_:didFind:moreComing:) but I can't see an equivalent for NWBrowser.
The only method I can think of is to apply a short time out.
Bonjour has no concept of a browse operation being ‘finished’. A browse will continue to send you updates as long as you leave it running. A browse only finishes when you cancel it.
The [deprecated] NetServiceBrowser had a [moreComing flag]
That flag doesn’t do what you think it does. Here’s what happens with the old API:
-
The Bonjour daemon receives a browse response packet with multiple answers [1].
-
It sends the first answer to your app. It can only send one answer at a time, so it sets the ‘more coming’ flag.
-
It continues to do this until the last answer.
-
For the last answer it clears the ‘more coming’ flag.
The intention is that your app can use this flag to defer updates, so that the list of services you show to the user doesn’t refresh a bazillion times while the initial set of results is coming in.
NWBrowser
doesn’t have this problem because it can deliver answers to you en masse.
The only method I can think of is to apply a short time out.
That’s rarely the right option when it comes to Bonjour. What are you actually doing with these browse results?
Most folks display them in a UI, so there’s no need for a timeout. Rather, you cancel the browse when the user moves away from that UI.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] Well, more likely it has these answers cached, but the story is the same either way.