The Apple Core Data Framework provides generalized and automated solutions to common tasks associated with object life-cycle and object graph management, including persistence. You can read more about Core Data in the Apple documentation here.
Amazon DynamoDB is a fast, highly scalable, highly available, cost-effective, non-relational database service. Amazon DynamoDB removes traditional scalability limitations on data storage while maintaining low latency and predictable performance.
The AWS Persistence Framework for Core Data bring these two technologies together to allow iOS developers to write Core Data applications that use Amazon DynamoDB as a persistence backend.
The AWS Persistence Framework for Core Data is compatible with iOS versions 5.0 and later.
Adding the AWS Persistence Framework for Core Data to your project is no different than adding any other framework to your project. After creating your Core Data enabled application, navigate to your project properties and go to the Build Phases tab. Select Link Binary With Libraries and hit the plus button to add both of the following frameworks:
After creating your Entity/Relationship model and generating your NSManagedObject subclasses, you will need to configure the persistence store in your application.
Your application will need to register that it will use Amazon DynamoDB as its backend store. This can all be placed in the AppDelegate, as part of the persistentStoreCoordinator selector.
[NSPersistentStoreCoordinator registerStoreClass:[AWSPersistenceDynamoDBIncrementalStore class] forStoreType:AWSPersistenceDynamoDBIncrementalStoreType]; persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; |
Your application will need to create a number of mappings to allow the Framework to understand how to handle its managed objects. These include:
NSDictionary *hashKeys = [NSDictionary dictionaryWithObjectsAndKeys: @"hashkeyAttributeName1", @"Entity1", @"hashkeyAttributeName2", @"Entity2", nil]; |
NSDictionary *versions = [NSDictionary dictionaryWithObjectsAndKeys: @"versionAttribute1", @"Entity1", @"versionAttribute2", @"Entity2", nil]; |
NSDictionary *tableMapper = [NSDictionary dictionaryWithObjectsAndKeys: @"tableName1", @"Entity1", @"tableName2", @"Entity2", nil]; |
With the mappings created, you next create a larger options dictionary. You also need to create an Amazon DynamoDB client object with AmazonCredentialProvider, and include it in the options dictionary. The AWS Persistence Framework for Core Data uses this client object to make requests to Amazon DynamoDB.
AmazonClientManager *provider = [AmazonClientManager new]; AmazonDynamoDBClient *ddb = [[AmazonDynamoDBClient alloc] initWithCredentialsProvider:provider]; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: hashKeys, AWSPersistenceDynamoDBHashKey, versions, AWSPersistenceDynamoDBVersionKey, tableMapper, AWSPersistenceDynamoDBTableMapper, ddb, AWSPersistenceDynamoDBClient, nil]; |
Finally your application will need to pass this options dictionary to the persistance store and check for error.
if(![persistentStoreCoordinator addPersistentStoreWithType:AWSPersistenceDynamoDBIncrementalStoreType configuration:nil URL:nil options:options error:&error]) { // Handle the error. NSLog(@"error: %@", error); } |
When using the AWS Persistence Framework for Core Data on multiple threads or devices, you
may encounter a situation where you need to resolve inconsistencies between data on
Amazon DynamoDB tables and your local copy in memory. When the conflicts are detected,
NSManagedObjectContext
returns an NSError
object and your
change will not be persisted. You can change this behavior by setting a merge policy
to your NSManagedObjectContext
:
managedObjectContext.mergePolicy = [[[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyStoreTrumpMergePolicyType] autorelease]; |
There are five NSMergePolicyTypes available: NSErrorMergePolicyType
(default), NSMergeByPropertyStoreTrumpMergePolicyType
,
NSMergeByPropertyObjectTrumpMergePolicyType
, NSOverwriteMergePolicyType
, and
NSRollbackMergePolicyType
. The AWS Persistence Framework for Core Data can
handle all five merge policy types. For more information about
NSMergePolicy
, please read NSMergePolicy Class Reference.
Because NSManagedObject
instances returned by Core Data are lazily loaded, it is
possible that when you access an attribute of an object, the actual row in the Amazon
DynamoDB table has been already deleted. In this situation, the AWS Persistence
Framework for Core Data will return an empty NSManagedObject
(the accessor
will return nil) and sends out
AWSPersistenceDynamoDBObjectDeletedNotification
. You can register to
observe AWSPersistenceDynamoDBObjectDeletedNotification
by calling the
following method:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeDeletedObject:) name:AWSPersistenceDynamoDBObjectDeletedNotification object:nil]; |
When you receive the notification, you should remove any invalid objects from local cache and
refresh the NSManagedObject
instance as necessary. The notification object
has a userInfo
dictionary, which you can use to identify the deleted
object, containing:
AWSPersistenceDynamoDBObjectDeletedNotificationHashKey
keyAWSPersistenceDynamoDBObjectDeletedNotificationEntityName
keyNSManagedObjectID
of the deleted object with AWSPersistenceDynamoDBObjectDeletedNotificationObjectID
keyThe following line shows how to refresh an NSManagedObject
. Please note that
refreshing an NSManagedObject
will send a getItem request to the Amazon
DynamoDB.
[managedObjectContext refreshObject:managedObject mergeChanges:YES]; |
Under heavily concurrent environments, periodically calling the refreshObject
method may reduce inconsistent states. Also, calling the refreshObject
method before saving the change will minimize inconsistent states to be persisted to the
Amazon DynamoDB tables.
Although the AWS Persistence Framework for Core Data was developed to meet the widest use case possible, it does have certain limitations.
NSError
object.NSManagedObject
subclasses, make sure this
option is not enabled.NSPredicates
are
limited to only the properties that are mapped to hash keys."hashKey1=value1" | supported, one hashKey and one value |
"hashKey1 = value1 OR hashkey1 = value2" | not supported, one haskKey, but two values |
"hashKey1 IN (value1, value2)" | not supported, one haskKey, but two values |
Please feel free to ask questions or provide comments in the Mobile Development Forum.