Search code examples
iosswiftswift3bonjour

Bonjour service discovery not finding hosts


I am trying to implement the Bonjour NetServiceBrowser in Swift3 in order to discover hosts on my network.

When I manually search in the terminal using the following command I will find the hosts.

dns-sd -B

However, when I try to use the NetServiceBrowser in Swift (see code below), it will only print "starting search..". I implemented this class by following the Bonjour documentation.

I do not understand what is going wrong. Does Bonjour work different for Swift? I could not find a working example online. I have tried several variants on the domain ("local", "local.", "") or several variants for name.

class ZeroConf: NSObject, NetServiceBrowserDelegate, NetServiceDelegate{

    var browser: NetServiceBrowser!
    var services = [NetService]()
    let domain = "local"
    let name = "_http._tcp"



    func startSearch(){
        self.services.removeAll()
        self.browser = NetServiceBrowser()
        self.browser.delegate = self
        self.browser.searchForServices(ofType: name, inDomain: domain)
    }


    func netService(_ sender: NetService, didNotPublish errorDict: [String : NSNumber]) {
        debugPrint(errorDict)
    }

    func netServiceBrowserWillSearch(_ browser: NetServiceBrowser) {
        print("starting search..")
    }

    func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser) {
        print("Stoped search")
    }

    func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) {
        print("error in search")
        debugPrint(errorDict)
    }

    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
        print("found service")
        services.append(service)
        debugPrint(service)
    }

    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
        if let ix = self.services.index(of:service) {
            self.services.remove(at:ix)
            print("removing a service")
        }
    }

    func netServiceDidResolveAddress(_ sender: NetService) {
        print("did resolve address")
    }
}

Solution

  • I found out why it wasn't working for me. I tried to execute the code from the main loop while it apparently should be called from a different thread. Hence, I changed my code in startSearch to

    DispatchQueue.main.async {
            self.browser.schedule(in: RunLoop.current, forMode: .defaultRunLoopMode)
            self.browser.searchForServices(ofType: self.name, inDomain: self.domain)
            RunLoop.current.run()
    }