App Development

Introducing WTAData Library

Mobile applications today are increasingly interconnected and data centric, relying on back-end infrastructures to provide the information displayed within the app. With this level of connectivity comes increased complexity. Slow or spotty network connections can have a large impact on the performance of these connected applications. To alleviate slow user interface experiences, the iOS team has increasingly leaned on using Apple’s CoreData framework. Apple’s framework allows us to store and persist network response data to lower the number of network calls that are necessary as a user navigates through the application.

In the past, we utilized several open-source libraries to ease the integration of CoreData. Over time, however, these libraries have either become more complex than our needs required or have not kept up with the pace of iOS changes. To solve this problem we created our own library, WTAData. The goal of WTAData is to provide a simple and straightforward set of utilities for interacting with CoreData.

Overview of WTAData

WTAData provides several pieces of functionality: a CoreData stack with persistent coordinator, managed object categories, and data importing. For the CoreData stack, we based our design on the 3rd stack presented by Florian Kugler in his excellent blog post, Concurrent Core Data Stacks, Performance Shootout. The basic structure of this stack is two independent managed object contexts that are connected to the same persistent store coordinator. One of the contexts is set up on a background queue, and the other is setup on the main queue. Changes are propagated between the contexts using the NSManagedObjectContextDidSaveNotification, which triggers the main context to merge the changes using merge ChangesFromContextDidSaveNotification:. This setup is extremely performant, and we have already seen performance increases in our existing apps by switching to this model.

Setting Up WTAData

Setting up WTAData within your own application is extremely easy. To utilize the default setup, WTAData can be initialized with one line of code:

WTAData *data = [[WTAData alloc] initWithModelNamed:@"WTADataExample"];

In addition to the default initialization, you can also specify more detailed setups such as in-memory stores using the WTADataConfiguration object.

// Initialize a new configuration
WTADataConfiguration *configuration = [WTADataConfiguration defaultConfigurationWithModelNamed:@"WTADataExample"];

// Set flag for deleting the store on a model mis-match
[configuration setShouldDeleteStoreFileOnModelMismatch:YES];

// Set flag for deleting the store on sql integrity errors
[configuration setShouldDeleteStoreFileOnIntegrityErrors:YES];

// Set flag for using an in-memory store
[configuration setShouldUseInMemoryStore:YES];

[[WTAData alloc] initWithConfiguration:configuration];

Saving and Accessing Data

The typical use case for WTAData is to use the background context to save data coming in from API calls or another source and to read and update the UI by accessing the main context. For example, to save a new item asynchronously and have it update the main context is as simple as the following lines of code:

[wtaDataInstance saveInBackground:^(NSManagedObjectContext *context) {
    Entity *entity = [Entity createEntityInContext:context];
    entity.stringAttribute = [NSString stringWithFormat:@"Entity Created"];
  } completion:^(BOOL savedChanges, NSError *error) {
    NSLog(@"Changes saved %d with error %@", savedChanges, error);

Fetching data from the store is also easy using the managed object categories provided by WTAData.

WTAData *data = <initialized instance of WTAData>
NSError *error = nil;

// Fetch all objects of a given type
NSArray *allObjects = [ManagedObject fetchInContext:data.mainContext error:&error];

// Fetch first object
ManagedObject *object = [ManagedObject fetchFirstInContext:data.mainContext error:&error];

// Create a fetched results controller for an object type
NSFetchedResultsController *controller = [ManagedObject fetchControllerInContext:data.mainContext                                              
                                                                sortDescriptors:<sort descriptor array>];

Creating and Deleting Objects

WTAData also provides simple mechanisms for creating or deleting objects.

// Create an object
ManagedObject *object = [ManagedObject createEntityInContext:data.mainContext];

// Delete all objects from the context
[ManagedObject deleteAllInContext:data.mainContext];

Importing Data

WTAData also provides support for importing large data sets, such as JSON API responses, into CoreData. WTAData can automatically map dictionary keys to your entity property names. If the mapping between the dictionary key and the entity property differ, then a mapping between those two values can be specified by setting an ImportName key on your entity’s User Info. Once the mappings are set up, an array of dictionaries can be imported with the following code:

[ManagedObject importEntitiesFromArray:<dictionary array> context:data.backgroundContext];

Additional Information

WTAData is available under the MIT license on GitHub and full documentation is available on CocoaDocs. WTAData is also available as a Cocoapod. We hope that you find this library useful and we welcome pull requests and bug reports on our GitHub repository. Happy Coding!

Security Scanning and Automation in a CI/CD Pipeline: Being Proactive In Security

Exposition How do we make our applications more secure upon release? Over the...

Read the article