Monday, 13 August 2012

Lightweight Database Migration in CoreData



Lightweight Migration:

This is an automatic feature of Core Data, but is limited to only simple migrations.
You can use this technique if the changes are among the following:
1. Adding a new attribute to an entity.
2. Renaming of an entity or an attribute.
3. Changing an attribute to optional or non-optional, whether it requires a value on creation.

Schema Changes, Versioning and Migrations
When you are developing an application you will almost never get the schema right the first time. So, Core Data has support for schema versioning and data migration. This allows you to define a new version of the Core Data schema by adding a new attribute or entity to the store. Then define how the store has to migrate from one change to another.


Creating a new xcdatamodel (Xcode 4.3.2)

If you want to do a lightweight migration first step is to create a new xcdatamodel for new schema.

1. Click on your xcdatamodeld file present in bundle.
2. Click on Editor Menu and select Add Model Version.
3.

4. Here specify the version name and Base Model and click Finish.
5. And you will find the newly created xcdatamodel file under the xcdatamodeld group.
6. Now click on xcdatamodeld in bundle and open File Inspector, under Versioned Core Data Model select the newly created xcdatamodel file.
7.

8. A green Tick will appear to left of the currently selected xcdatamodel file.
9.


10. And now you are done with data migration, now Core Data will automatically handle the new schema for the database.


11. Set the Persistent Store options for automatic migration in AppDelegate

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"YOURDB.sqlite"];
//Enabling automatic migrations in persistent store coordinator
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}



Handling Multiple API calls in same UIController class


Problem:
I was facing problem in handling multiple API calls in same UIController class, as responses of all come into same delegate method named "requestFinished" and we have to use flags & if-else loops for handling each response.

Solution:
1. In this code i have made 3 Asynchronous API calls in same UIController class.
2. On button action all 3 API web metods are called at once.
3. For handling each API i have made a separate NSObject class.
4. I am passing API urls from UIController class to their respective NSObject class.
5. When API is called, control is handled to its respective NSObject class.
6. Each NSObject class has its own delegate method named "requestFinished" to handle API response.
7. As API response is received control is again passed on to UIController class.
8. In this manner we can make Multiple Async API calls at once from same UIController class.

In some cases one API call depends on other API call response. In such situation just call First API and when the its response is passed on to UIController class from NSObject class, call the Second API at that point.

You can download code from here:

Multiple-API-Calls-Handling