Creating Data
Basic Transactions
Similar to the Retrieving Data chapter, transacting data against Liquid Server extremely easy with the Liquid Core API using LDMDataManager.
- (void)persistItem:(LDMItem *)item withCompletionHandler:(void (^)(BOOL success))completionHandler;
- (void)transactCreateOrUpdateWithItem:(LDMItem *)item withCompletionHandler:(void (^)(BOOL success))completionHandler;
First let's discuss the fundamental difference between persist and transact an item. Persist performs a Save, which is a one way transaction to the server. When using this operation, do not expect acknowledgment from the server.
Transact create or update will send a Create if it's a brand new item, or Update if the item already exists. When using this operation, you should expect an acknowledgment from the server and client code should handle the round trip notifications accordingly (section below).
Using persist at the right time can heavily reduce the overhead for communication between the client and server. This operation should be used when:
- The item being persisted is only entitled to one user
- You expect to modify the item numerous times and you expect the version of the item you send out with a save is always the final version
In order to call persist on an item, the schema requires some special configuration.
"supportedOperations": [
"Save"
],
For the most part, the methods with the completion handler will be the ones you use. If you're in a separate thread already, you may use the synchronous version of the same call. Please see the API section for more information. In either case, the transaction handler will be called after the changes to the item has been written locally to the database, and the item is queued up to be sent to the server. To get notified of when the item returns back from the server, please see the next section.
Adding Observers
As part of the Liquid Core API, there are some extensions on top of the existing Apple Notification API that helps add observers to a particular item or item type. This is the best way to refresh UI after the data you're interested in has completed round trip to other back end systems.
#import <LiquidPlatformKit/NSNotificationCenter+LDMExtensions.h>
@property id cartObserver
@property (strong) LDMItem currentCart
First, use the include statement above to include the necessary extensions. Create a property of type id which will be your observer. In the example to follow, we will be be interested in being notified when the something happens to a cart item (in this case, the property currentCart).
self.cartObserver = [[NSNotificationCenter defaultCenter] addObserverForItem:currentCart usingBlock:^(LDMItem *aItem){
if (aItem == nil)
//the cart you're observing no longer exists, refresh UI
else
{
[self.currentCart copyHeaderAndDataFromItem:aItem];
//update UI here
}
)];
So with the code above there a few interesting things. First we create the observer in a very similar fashion to the standard Apple notification API, passing in the current LDMItem of interest. There is also a block / callback for when any time the item is changed. If the item is deleted, the parameter passed in is nil. Otherwise, we call a method on the LDMItem, which copies all the data to the current item you're already referencing.
Finally, just like any other NSNotification, don't forget to remove it on the methods dealloc method or else you'll have a memory leak.
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (self.cartObserver != nil)
{
[[NSNotificationCenter defaultCenter] removeObserver:self.cartObserver];
self.cartObserver = nil;
}
}
If you're interested in in attaching an observer for a particular item type, you can use the method below.
- (id)addObserverForItemType:(NSString *)itemType usingBlock:(void (^)(NSDictionary *changesForTypeById, NSArray *deletesForTypeById))block
It is less common to attach an observer to a single item type, but really depends on the use case. For example if there was a list view showing "All Accounts", and the UI needed to refresh when accounts are added / deleted, then the signature above is the most appropriate for that situation.
Sync States
When an item is transacted and synced to the server (or vice versa), they go through a series of states. In iOS, it is presented with the following enumeration.
typedef enum {
LDMSyncStatusPending = 0,
LDMSyncStatusInTransit,
LDMSyncStatusDelivered,
LDMSyncStatusReceived
} LDMSyncStatus;
- An item can be rejected from the server for various reasons. One of the most common rejection reasons is TransactionInProgressForItem, which means the item you're trying to modify is currently in the middle of a transaction to another back end system, and that system has not yet responded. For example, a cart has been sent to SAP for processing, but the cart is large and takes a long time to process. In this situation, the item goes back into the pending queue. If the item is rejected for the same reason three times, the client no longer attempts to send the item to the server. In the situation where the item doesn't warrant a retry, the receipt message is updated, and the develper will have to handle this accordingly.