Retrieving Data

LDPlatform makes it easy to retrieve data from the local database, but also data directly from Liquid Server. In addition, we provide one simple delegate and data structure to work with so that you can easily show the data on the iOS UI components, such as a table or collection view.

We'll discuss two different ways of retrieving data, each with their own sets of strengths and weaknesses.

Using LDMDataManager

LDMDataManager offers a number of quick ways of retrieving data from the local database. Reminder that only data entitled to the user gets synced down to the device.

- (LDMItem* __nullable)itemOfType:(NSString*)typeName withId:(NSString*)objectId
- (NSArray*)allItemsOfType:(NSString*)typeName;

The API chapter describes the methods above in greater detail but here are a few examples of how to use the methods above

itemOfType

-(void) updateLabel
{
  //executing on the main thread only as an example
  LDMItem *account = [[LDMDataManager sharedInstance] itemOfType:@"Account" withId:@"account12345"];
  if (account)
     self.someLabel.text = [account valueForKey:@"accountName"];
}

In the example above, we're hitting the local database, to see if there is an item of type Account with an id of account12345. To be more specific, we're seeing if there's an account with an h_id or a h_clientId or a primary key (for instance accountId) with an id of account12345. The code above would generate the SQL equivalent of:

select * from DemoCommunity_entity_Account t where 
t.h_id = 'account12345' or t.h_clientId = 'account12345' 
or t.accountId = 'account12345'

Using itemOfType can often times be useful since it is the easiest way of obtain one particular item of a specific type and ID. In basic scenarios this is usually recommended, especially when starting out This is often recommended if you are retrieving a specific configuration item in your custom UI, since that will rarely change. As use cases get more complicated, this method is rarely used in real life scenarios to retrieve data.

allItemsOfType

-(void) updateTables
{
  //executing on the main thread only as an example
  NSArray *accounts = [[LDMDataManager sharedInstance] allItemsOfType:@"Account"];
  self.tableData = accounts;
  [self refreshTables]; 
}

In the example above, we're retrieving all items of type Account in the local database. This is also a great starter method for getting warmed up to LDPlatform. This method should only be used when the expected data set is relatively small (less than 100 items), since every item will go directly into memory. This method is great for POCs and can be easily used as the underlying data for a UITableView. Again, as use cases get more complicated, this method is rarely used.

The code above would generate the SQL equivalent of:

select * from DemoCommunity_entity_Account t

Using Function Items and LDMSearchResults

While using LDMDataManager and the described methods above you can easily get one or all items of a particular type, it is a fairly limiting operation. Using Function Items you can have your UI load data on a configuration driven item. A few steps are required in order to get this working.

Create Your Function Item

In Mission Control, go to item blotter Function and create a new item. For the purpose of this book, you can use the JSON item below.

  "data": {
    "feed": "",
    "function": "{\"selectCore\": \"from _entity_Account t where t.accountType = 'ForeignStores' \", \"tableAlias\": \"t\", \"containsWhere\": true, \"faultBlocks\": false, \"orderedBy\": \"accountName DESC\", \"segmentedBy\": []}",
    "functionId": "AccountsByType",
    "functionName": "AccountsByType",
    "functionType": "/Function/functionType[SQLiteQuery]",
    "itemType": "Account",
    "order": 0.0,
    "clientConfig": ""
  }

There are 3 important things to notice from the item posted above.

  1. The functionId is unique, and this is the string that needs to be referenced in code later on.
  2. itemType must be filled in correctly so that the system knows what item you are expecting back, in this case Account.
  3. function contains a dictionary with various parameters, the minimum being selectCore (the fundamental component of your query). More information can be found about SQLiteQuery and RDSQuery later in this chapter.

Now that we have a proper Function item, let's hook up the correct components in code. In the UI class if you wish to show the list of items, you'll have to implement LDMSearchResultsDelegate

- (void)searchResultsDidAddNewRows:(LDMSearchResults *)results;
@optional
- (void)handleFetchError:(NSError *)error;

searchResultsDidAddNewRows will get called any time there is a change to the data set. Implementing LDMSearchResultsDelegate in your UI class is the only practical way to scroll through large sets of data, as pagination automatically happens. As you scroll, the result LDMSearchResults will automatically know when to fetch the next or previous page depending which direction you're scrolling. Using this dataset, we also give you the ability to retrieve the Title. This is required when scrolling through a data dataset, sorted by an alphanumeric field, and you wish to use the iOS rolodex. Below is a sample implementation for methods used in UITableView.

-(void) refreshData
{

  LDMItem *functionItem = [[LDMDataManager sharedInstance] itemOfType:@"Function" withId:@"AccountsByType"];
  [LDMFunction allItemsFromFunctionItem:functionItem rowLimit:0 withQueryFilter:nil faultBlocks:NO withBlock:^(LDMSearchResults *results) {

              self.results = results;
              self.results.delegate = self;
              if ([results count] == 0)
              {
                  dispatch_async(dispatch_get_main_queue(), ^{
                      [self.tableView reloadData];
                      [self.countLabel setText:@"Total Count: 0"];
                  });
              }
   } withContext:self.context];
}

- (void)searchResultsDidAddNewRows:(LDMSearchResults *)results
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView reloadData];
        [self.countLabel setText:[NSString stringWithFormat:@"Total Count: %d", (int)results.count]];
    });
}

-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    NSArray *titles = [self.results sectionIndexTitles];
    return titles.count == 1 ? nil : titles;
}

-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
    if ([self.results isKindOfClass:[LDMSearchResultsPaginated class]])
        return index;

    return [self.results sectionForSectionIndexTitle:title atIndex:index];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [self numberOfRowsInSection:section];
}

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    LDMItem *item = [self.results objectForRowAtIndexPath:indexPath];
    //do something with item
}

Using function items as a way to retrieve data is extremely powerful for a few reasons.

  • Your code is only binded to a function called AccountsByType (in code), which is a configuration item that lives on the server. If you ever need to change the logic of the query, the iOS application does not need to be touched (for the most part). Say you wanted to add an additional clause to the SQL: "t.accountType = 'ForeignStores' OR t.accountType = 'localStores', this logic could be modified by directly modifying the Function item in MC.

results matching ""

    No results matching ""