Search code examples
swiftswift3bonjournsnetservicensnetservicebrowser

Bonjour Service Browser with Swift does not fetch serviceinfo


The service I want to connect to is published via Bonjour.
I can find all the info with the Bonjour Browser, however if I try to gather the data programmatically, the only value I get, is the name of the service.

The NetService delegate is set and the function netServiceWillPublish is called. The functions DidNotPublish or DidPublish are not executed.

The function netServiceBrowser gets all published netServices, but all properties are set to the default value of the datatype.

import UIKit

class BMNSDelegate : NSObject, NetServiceDelegate {
    func netServiceWillPublish(_ sender: NetService) {
        print("netServiceWillPublish:\(sender)");  //This method is called
    }


    func netService(_ sender: NetService, didNotPublish errorDict: [String : NSNumber]){ 
        print("didNotPublish:\(sender)");
    }

    func netServiceDidPublish(_ sender: NetService) {
        print("netServiceDidPublish:\(sender)");
    }
    func netServiceWillResolve(_ sender: NetService) {
        print("netServiceWillResolve:\(sender)");
    }

    func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) {
        print("netServiceDidNotResolve:\(sender)");
    }

    func netServiceDidResolveAddress(_ sender: NetService) {
        print("netServiceDidResolve:\(sender)");
    }

    func netService(_ sender: NetService, didUpdateTXTRecord data: Data) {
        print("netServiceDidUpdateTXTRecordData:\(sender)");
    }

    func netServiceDidStop(_ sender: NetService) {
        print("netServiceDidStopService:\(sender)");
    }

    func netService(_ sender: NetService,
                    didAcceptConnectionWith inputStream: InputStream,
                    outputStream stream: OutputStream) {
        print("netServiceDidAcceptConnection:\(sender)");
    }
}

class BMBrowserDelegate : NSObject, NetServiceBrowserDelegate, NetServiceDelegate {

    func netServiceBrowser(_ netServiceBrowser: NetServiceBrowser,
                           didFind netService: NetService,
                           moreComing moreServicesComing: Bool) {
        let nsnsdel = BMNSDelegate()
        netService.delegate = nsnsdel
        netService.resolve(withTimeout: 1)
        print(netService.domain) // local.
        print(netService.name) // This property is correct
        print(netService.type) // _http._tcp.
        print(netService.addresses) // Optional([])
        print(netService.hostName) // nil
        print(netService.port) // -1
        print(moreServicesComing) //false
    }

}


let SERVICE_TYPE = "_http._tcp."
let BM_DOMAIN = "local."
let browser = NetServiceBrowser()
let nsbdel = BMBrowserDelegate()
browser.delegate = nsbdel
browser.searchForServices(ofType: SERVICE_TYPE, inDomain:         BM_DOMAIN)
RunLoop.current.run()

Solution

  • The error is that the services which are found in the ServiceBrowserDelegate function are not saved anywhere and therefore are discarded at the end of the function.

    I found a working example here:
    https://github.com/mattneub/Programming-iOS-Book-Examples/blob/61f0c753a080040e4a74b912e6c18dd97fe8bcaa/bk2ch24p853bonjour/ch37p1101bonjour/ViewController.swift

    class ViewController: UIViewController, NetServiceBrowserDelegate, NetServiceDelegate {
    var nsb : NetServiceBrowser!
    var services = [NetService]()
    
    @IBAction func doButton (_ sender: Any!) {
        print("listening for services...")
        self.services.removeAll()
        self.nsb = NetServiceBrowser()
        self.nsb.delegate = self
        self.nsb.searchForServices(ofType:"_daap._tcp", inDomain: "")
    }
    
    func updateInterface () {
        for service in self.services {
            if service.port == -1 {
                print("service \(service.name) of type \(service.type)" +
                    " not yet resolved")
                service.delegate = self
                service.resolve(withTimeout:10)
            } else {
                print("service \(service.name) of type \(service.type)," +
                    "port \(service.port), addresses \(service.addresses)")
            }
        }
    }
    
    func netServiceDidResolveAddress(_ sender: NetService) {
        self.updateInterface()
    }
    
    func netServiceBrowser(_ aNetServiceBrowser: NetServiceBrowser, didFind aNetService: NetService, moreComing: Bool) {
        print("adding a service")
        self.services.append(aNetService)
        if !moreComing {
            self.updateInterface()
        }
    }
    
    func netServiceBrowser(_ aNetServiceBrowser: NetServiceBrowser, didRemove aNetService: NetService, moreComing: Bool) {
        if let ix = self.services.index(of:aNetService) {
            self.services.remove(at:ix)
            print("removing a service")
            if !moreComing {
                self.updateInterface()
            }
        }
      }
    }