Hello,
In the documentation for Foundation's NetServiceBrowser (https://developer.apple.com/documentation/foundation/netservicebrowser) it states:
"To use an
NSNetServiceBrowser
object to search for services, allocate it, initialize it, and assign a delegate. (If you wish, you can also use the schedule(in:forMode:)
and remove(from:forMode:)
methods to execute searches on a run loop other than the current one.) Once your object is ready, you begin by gathering the list of accessible domains using either the searchForRegistrationDomains()
or searchForBrowsableDomains()
methods. From the list of returned domains, you can pick one and use the searchForServices(ofType:inDomain:)
method to search for services in that domain."However, that's not quite true. There must be a call to the stop() function of the browser before searches work.
e.g. if you place the code below into a Swift Playground you get the error:
Didn't search for service because: ["NSNetServicesErrorDomain": 10, "NSNetServicesErrorCode": -72003]
If you uncomment line 21 then the code works. Why does one have to call stop() on the NetServiceBrowser before searching, and shouldn't the docs mention this?
Thanks.
import Foundation
class DenonFinder: NSObject, NetServiceBrowserDelegate {
let browser = NetServiceBrowser()
func start() {
browser.delegate = self
print("Search for registration domains")
browser.searchForRegistrationDomains()
}
//MARK: NetServiceBrowserDelegate
func netServiceBrowser(_ browser: NetServiceBrowser, didFindDomain domainString: String, moreComing: Bool) {
print("didFindDomain: \(domainString)")
if (moreComing) {
print("moreComing")
}
// Why must stop be called before search?
// browser.stop()
let webService = "_http._tcp."
print("searchForServices: \(webService) in domain \(domainString)")
browser.searchForServices(ofType: webService, inDomain: domainString)
}
func netServiceBrowserWillSearch(_ browser: NetServiceBrowser) {
print("Search about to begin")
}
func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) {
print("Resolve error:", sender, errorDict)
}
func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser) {
print("Search stopped")
}
func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
print("Service found: \(service)")
if (moreComing) {
print("moreComing")
} else {
browser.stop()
}
}
func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
print("Service went away: \(service)")
}
func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) {
print("Didn't search for service because: \(errorDict)")
}
}
class MainApplication {
let runLoop = RunLoop.current
let distantFuture = Date.distantFuture
// let testTimer = Timer.scheduledTimer(withTimeInterval: 4.0, repeats: false, block: {_ in print("timer fired")})
let denonFinder = DenonFinder()
/// Set this to false when we want to exit the app...
var shouldKeepRunning = true
init() {
denonFinder.start()
}
func run() {
while shouldKeepRunning == true &&
runLoop.run(mode:.default, before: distantFuture) {}
}
}
// Entry Point
let app = MainApplication()
app.run()
The error you’re seeing, -72003, is not public but it translates to
kCFNetServiceErrorInProgress
. The issue here is that you’re using the same
NetServiceBrowser
object for two tasks:
Searching for registration domains, via
searchForRegistrationDomains
Searching for services, via
searchForServices(ofType:inDomain:)
An
NetServiceBrowser
object can only do one thing at a time, so if you try to start a service search while you’re already doing a registration domain search it fails with this error.
Why are you search for registration domains as part of a browser? Most folks implementing a browser only search for services, pass in the empty string as the domain parameter so that they automatically search all browsable domains. In advanced applications it can make sense to search for browsable domains, using
-searchForBrowsableDomains
, and then search for services independently in each domain. I can’t think of any reason why you’d want to search for registration domains as part of a browser.
Also, if you’re not already familiar with
NWBrowser
, you should check it out.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"