oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Incorporating Rendezvous into Your Cocoa Applications, Part 2
Pages: 1, 2, 3, 4

Setting Up The Browser

Browsing is where Rendezvous really shines: it is the pinnacle of user-friendliness when a user, without any effort, can see listed, before his eyes, the services available for his use. You just can't get much simpler. Fortunately for us application developers, wiring up a Rendezvous service browser is nearly as simple.

NSNetServiceBrowser supports two kinds of searching: we can search for domains on which services might exist, and we can search for all services on a specific domain. We will explore both, but only the latter is supported in the RCE user interface.

As we did with NSNetService, we will implement delegate methods of NSNetServiceBrowser that will drive the interface in response to discovery events. For example, if a service is registered on the network, our NSNetServiceBrowser object will notify its delegate, the Controller object, of the discovery by invoking the delegate method netServiceBrowser:didFindService:moreComing:.

Before we get to implementing the delegate methods, we'll set up the browser object in the method setupBrowser. This method is the following:

- (void)setupBrowser
    if ( !serviceBrowser ) {
	       serviceBrowser = [[NSNetServiceBrowser alloc] init];
	       [serviceBrowser setDelegate:self];
    if ( !domainBrowswer) {
        domainBrowser = [[NSNetServiceBrowser alloc] init];
        [domainBrowser setDelegate:self];
    if ( !discoveredServices )
	       discoveredServices = [[NSMutableArray alloc] init];

    [domainBrowser searchForAllDomains];
    [serviceBrowser searchForServicesOfType:@"_rce._tcp." inDomain:@""];

First we do some lazy initialization of the serviceBrowser and domainBrowser objects: if they don't exist yet, we create them, otherwise we continue on with the method. We do the same thing with the mutable array discoveredServices. All three of these objects should be declared as instance variables in the interface, which will give us the final set of instance variable declarations shown here:

@interface Controller : NSObject
    NSNetService *service;
    NSNetServiceBrowser *serviceBrowser;
    NSNetServiceBrowser *domainBrowser;
    NSMutableArray *discoveredServices;
    NSSocketPort *socketPort;
    NSFileHandle *listeningSocket;
    IBOutlet id discoveredServicesList;
    IBOutlet id nameField;

Creating an instance of NSNetServiceBrowser is as easy as invoking alloc and init in NSNetServiceBrowser. At the same time we create each instance of NSNetServiceBrowser, we assign self as the delegate so our Controller object can be alerted to newly-discovered domains, services and other events that occur in the event of searching. Next we do the same trick for the mutable array discoveredServices, which is declared in the interface as an instance variable. This array will provide the services table with its data through the NSTableView data source methods we will implement. Finally, we begin a search of services in the default domain that are of type _rce._tcp. by invoking the searchForServicesOfType:inDomain: method.

Note that an instance of NSNetServiceBrowser cannot simultaneously search for both domains and services: it's one or the other. However, if you did want to search for both domains and services concurrently, you could do so by having two instances of NSNetServiceBrowser: one to search for domains, and the other to search for services. This is exactly what we do in our application. While domain and service discovery are both supported, only service browsing is supported in our UI. Domain discovery is reported to the user only through output to stdout.

NSNetServiceBrowser Delegate Methods

NSNetServiceBrowser declares the following seven delegate methods:

  • netServiceBrowserDidNotSearch:
  • netServiceBrowserWillSearch:
  • netServiceBrowser:didStopSearch:
  • netServiceBrowser:didFindService:moreComing:
  • netServiceBrowser:didRemoveService:moreComing:
  • netServiceBrowser:didFindDomain:moreComing:
  • netServiceBrowser:didRemoveDomain:moreComing:

In each of these methods (except the first two), the browser object that invoked the method is passed in the netServiceBrowser: argument. In the first two, the browser object invoking the method is passed as the sole argument. For the sake of brevity, I will not type out the common netServiceBrowser prefix when referring to these methods.

The first three methods listed above, didNotSearch:, willSearch, and didStopSearch, notify the delegate about the progress or status of a search operation. Just before a search commences, when the search browser object has determined that the network is present and the browser object is configured correctly, it will invoke the method willSearch. The method didStopSearch is invoked in the delegate in response to a stop message being sent to the browser object that is currently searching.

NSNetServiceBrowser has an error-reporting method: netServiceBrowser:didNotSearch:. This method passes to the delegate the browser object reporting the error, as well as an error dictionary that contains the same keys as the NSNetService error dictionary described earlier.

The pair of methods didFindService:moreComing: and didRemoveService:moreComing: are used to report to the delegate the discovery and removal of services. The Service: arguments to these methods are instances of NSNetService representing the Rendezvous network service that has been discovered, or that was removed from the network.

The objects passed to us in didFindService:moreComing: and didRemoveService:moreComing: are not the same objects that services are published with. Rather, they are simply NSNetService instances that represent those services as something to which to connect. Unlike instances of NSNetService that are used to publish services, these NSNetService objects are appropriate only for resolving the discovered service.

Pages: 1, 2, 3, 4

Next Pagearrow