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 anROException
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];
});
});
}