Desktop

The DynamicSelect desktop sample demonstrates retrieving a table from an instance of Relativity Server where only certain fields are retrieved, using the getDataTable:select:where: method of DARemoteDataAdapter. This is useful when you are only interested in a subset of the data.

Getting Started

The Desktop sample is typically located in /Developer/RemObjects Software/Samples/Data Abstract/Desktop/DynamicSelect, though you may have installed the Data Abstract for Cocoa and it's samples in another location.

To build it, you will of course need Xcode, and like all the samples provided with Data Abstract for Cocoa you will need to be running the Relativity Server with the DASamples Domain and the Simple Schema available.

Running the Sample

This sample simply displays the results the contents of the Clients table from the Simple schema in the DASamples domain. The UI is split into 2 sections, a toolbar with buttons for all of the actions and a table for displaying all of the records in the Clients table.

The toolbar has only the one button and a popup. The "Dynamic Select" button retrieves the Clients table from the server, with each row only containing the Id, Name and Phone columns. The popup which contains a list of available servers discovered by the Zeroconf discovery system. When the sample is run, it starts a Zeroconf discovery service that looks for instances of Relativity Server running on the local network. Any discovered servers will be added to the popup, if no servers are discovered then the dropbox on the toolbar will be empty. You can specify a server address yourself by clicking on the popup and then clicking on "Specify custom URL...".

Examining the Code

The code for creating the connection to the server and handling logging in is covered by other samples. In this section we shall focus solely on how to use the getDataTable:select:where: method of DARemoteDataAdapter.

App Structure

The sample is built around four classes; AppDelegate, DataAccess, ServiceAccess, and RegisterServerWindowController.

The DataAccess class handles everything related to interacting with the Data Abstract SDK; including retrieving data from an instance of Relativity Server and applying changes back to the server. The code below is found in DataAccess.m.

The ServiceAccess class handles the discovery of any instances of Relativity Server that are available on the local network using ROZeroConf which is a feature available with the Remoting SDK that Data Abstract is built upon. ServiceAccess sets up a ROZeroConfBrowser Class object which searches for any servers that broadcast a value matching the value defined for RELATIVITY_SERVICE_NAME. When a service is found, or indeed disappears, the server list is updated and the popup with the list of available servers is also updated. It also handles the registration of custom server addresses. To explore further the ServiceAccess class and Zeroconf discovery see the article: The ServiceAccess Class and Zeroconf discovery.

The RegisterServerWindowController class is a subclass of NSWindowController which handles the UI aspects of a user manually adding a server url.

Lastly the AppDelegate class handles the primary setup of the application, registers that it will listen for notifications broadcast by the ServiceAccess and DataAccess classes, and acts as a delegate to the RegisterServiceWindowController, DataAccess and NSTableView classes. The only thing of note is that the dataIsReady: method which reloads the table to display the newly retrieved data when the notification NOTIFICATION_DATA_READY is received.

Retrieving selected fields

When you use getDataTable: to retrieve a DADataTable, the rows in the table contain all of the columns / fields. To selectively retrieve only certain fields, you need to use getDataTable:select:where: or its asynchronous variant beginGetDataTable:select:where:withBlock:.

The method takes three arguments:

  • The first is the name of the table to retrieve.
  • The second argument is an array of field names to selectively retrieve. The array passed to select: should contain strings which match the field names in the table, otherwise an ROException will be thrown.
  • The third argument is for an optional Dynamic Where clause. To see an example of using Dynamic Where see the Dynamic Where sample.

In this sample we create an array that contains FIELD_ID, FIELD_NAME and FIELD_PHONE (these are defined in DataAccess.h and equate to ClientId, ClientName and ClientPhone), though you could remove the comment to also add FIELD_EMAIL and / or FIELD_PASSWORD. The array is passed to the select: argument of getDataTable:select:where:, and a nil is passed to the where: argument as we aren't interested in it.

The result of the call in then assigned to the dataTable property of DataAccess, and a notification posted (NOTIFICATION_DATA_READY) that will cause AppDelegate to reload the table with the retrieved data.

// DataAccess.m
- (void)beginGetDataUsingDynamicSelect {

    NSArray *dynamicSelect = @[FIELD_ID, FIELD_NAME, /*FIELD_EMAIL, FIELD_PASSWORD,*/ FIELD_PHONE];
    NSLog(@"DynamicSelect: %@", [dynamicSelect componentsJoinedByString:@", "]);

    NSLog(@"Begin getting the data...");
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

        DADataTable * result = nil;

        @try {
            result = [self.dataAdapter getDataTable:@"Clients" select:dynamicSelect where:nil];
        }
        @catch (NSException * exception) {
            NSString * error = @"Error when downloading data";
            NSString * message = [NSString stringWithFormat:@"%@: %@", error, [exception reason]];
            NSLog(@"%@", message);
            [self.delegate alertError:error withDetails:[exception reason]];

            return;
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Data has been retrieved.");
            self.dataTable = result;
            [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DATA_READY object:self];
        });
    });
}