Hamish Rickerby

Mac and iPhone/iPad developer based in Melbourne, Australia

1000km - February

| Comments

Progress has been a bit slower this month. Short month, very hot here, and new baby all contributed to slowing progress down. Oh, in other news, we now have a baby! Exciting.

190km complete at end of Feb, which leaves me with a 30km buffer. The last graph was a little incorrect too – Numbers only puts dates correctly (in relative terms) on the x-axis if the graph type is a scatterplot. Dumb. The new graph below is correct.

1000km - January

| Comments

Progress on the 1000km is good so far. 109km run in Jan, and I’m sticking to the 10km distance per run. Weight is also starting to fall, which is great because I’m about 9kg heavier than I should be.

Because I’m also a nerd (and if you’re reading my blog, you probably are too), here’s a graph marking progress. Grey line is what I need to run to get to 1000km this year. Any blue higher than the grey line is kms in the bank for a rainy day.

Meteor

| Comments

A couple of days ago I received an email from meetup.com about meetups that I might be interested in. Usually this is full of crap I don’t care about, like mothers groups or salsa dancing, but this most recent mail featured an intriguing group called “Meteor Melbourne – a better way to build apps”. So, I looked into it.

Meteor is a framework based on node.js that allows you to write responsive, reactive, real-time web applications in javascript on both the client and server side. I’ve always considered javascript as a toy language – I think this opinion comes from my first interaction with JavaScript waaaaaay back in the late 90’s (I think it was somewhere between ‘96 and ‘98), when all it was really used for was alert boxes and tic-tac-toe implementations. However, I’ve recently been doing a lot of work for clients with Parse and their “cloud code” functionality, taking some logic out of mobile apps and running it on the Parse servers – and you use JavaScript to do this. They promoted use of Promises, and I’ve been doing a lot with RAC in iPhone apps, so this functional style is something I’m familiar with and like. I also have a friend who is helping a mate out on a startup, who is looking at some serious “enterprise” functionality implemented with server-side javascript, so I thought it was maybe time to seriously look at this thing too, and I checked it out.

Amazeballs. Meteor is MAGIC. Don’t believe me? Watch this screencast.

I think the magic for me comes from the real-time (well, super fast at least –> sub second synchronization) nature of the system, and the automate shuffling of data between the server and client to synchronize/update pages with no specific actions on the developers part. The built in support for packages is also really tidy, although having to use a 3rd party packages system (Meteorite and Atmosphere) for more modern versions of some of the core packages (eg, bootstrap-3 vs bootstrap-2) seems a little undesirable.

It’s super fast to get set up (1 line install, 1 line to start), and this includes server, database, sync between client and server. Want user authentication? Two more command line hits (1 for a UI, 1 for a login provider package), and 1 line to get the UI template built in. Amazingly productive.

Where I see huge potential for Meteor is in the mobile space. Having a web app, which automatically pushes changes to a mobile device is super powerful. With the current state of mobile apps you typically need to poll for changes to data, unless you build your own data sync solution or rely on something like iCloud to push changes around for you (haha, yeah right). When I’ve done this sort of thing in the past with Parse, I’ve actually gone as far as abusing the Apple Push Notification Service to actually trigger a mobile device to re-query a web service to retrieve new data as APNS is the only push mechanism available. Having a service that reliably notifies a client when data changes server side, with sub-second speed, solves a whole bunch of problems for app developers.

This is the tech stack that I’m now looking at using for my small business productivity tool, and I’m hoping that mobile sync works just as well (and fast) as the client-server sync does. Next up is a small proof of concept to test this out.

I haven’t been this excited about web development since I saw DHH’s web app in 15 mins rails screencast in 2006.

Oh yeah, I went to the meetup too. Nice job meetup.com

2014

| Comments

I’m not one for new years resolutions, but there are a couple of things I’d like to achieve this year.

  1. Run 1000km
  2. Design, Develop, and Release a productivity tool for small and medium businesses

1000km is something I attempted to achieve last year, but by the time February rolled around, it was obvious that that just was not going to happen. This year is going much better. I’ve established a running routine already, and have (as of today) extended my run distance to about 10km. I’m sure this will be much tougher when winter rolls around, but I’m up for the challenge.

The SME productivity tool is something I’ve been toying with the idea of for a while. The idea actually came from my sister and her husband (they run a construction company), and it solves a problem that they spend a few hours a week on. I’ve already got my minimum functionality defined, and business model. It works well as a SaaS/subscription style product so fits with the revenue stream style I like. I’ll hopefully have a splash/info/signup page soon. I’m also looking at a new (new for me) technology stack to power this thing, so I’ve also got a lot of learning to be able to create it. Fingers crossed it gets off the ground.

I guess there’s a third thing, but it’s more of an inevitability, rather than a goal as such. We’ll be having a baby soon (hopefully in 3 weeks), so life will be getting much more time-scarce. We’ll see how all this holds up under parenthood.

Medical Regulation and Apps

| Comments

Yesterday I read an article in Venture Beat covering part of a series of hearings US Congress is holding on regulation of health and medical apps on smartphone and tablet devices. My significantly paraphrased version of the article is that the FDA are unsure if and how health apps should be regulated, and that representatives from the “app” industry are pushing for no regulation for consumer facing apps.

I have a slightly different take on this. To me, the question is simple (and what is driving health authorities globally to address this issue): can health apps be considered to be medical devices?

Medical devices are subject to legislation worldwide. In fact, often requiring prior market approval through mechanisms similar to which pharmaceutical companies must obtain approval for medicines. Clear guidance exists on the regulation which surrounds medical devices, and this includes the legislative definition of what constitutes a medical device. As a snapshot (and these definitions can be considered consistent with legislation in many other countries too), the definition of a medical device in Australia, the EU, and US clearly includes apps which diagnose, prevent, monitor, treat, alleviate disease.

Australian Therapeutic Goods Act 1989link
1
2
3
4
5
6
7
8
41BD A medical device is:
  a. any instrument, apparatus, appliance, material or other article (whether used alone or in combination, and including the software necessary for its proper application) intended, by the person under whose name it is or is to be supplied, to be used for human beings for the purpose of one or more of the following:
    i. diagnosis, prevention, monitoring, treatment or alleviation of disease;
    ii. diagnosis, monitoring, treatment, alleviation of or compensation for an injury or handicap;
    iii. investigation, replacement or modification of the anatomy or of a physiological process;
    iv. control of conception;
  and that does not achieve its principal intended action in or on the human body by pharmacological, immunological or metabolic means, but that may be assisted in its function by such means; or
  b. an accessory to such an instrument, apparatus, appliance, material or other article.
EU Directive 2007/47/ec (paraphrased)
1
2
3
4
5
Any instrument, apparatus, appliance, software, material or other article that is used alone or in combination, including software specifically for diagnostic or therapeutic purposes, that the manufacturer intends for use in human beings. Such devices are used for:
 - Diagnosis, prevention, monitoring, treatment, or alleviation of disease
 - Diagnosis, monitoring, treatment, alleviation of, or compensation for an injury or handicap
 - Investigation, replacement, or modification of the anatomy or of a physiological process
 - Control of conception
US Food, Drug and Cosmetic Act Section 201(h)
1
2
3
4
Medical machine, contrivance, implant, in vitro reagent, or other similar or related article, including a component part, or accessory that is:
 - Recognized in the official National Formulary, or the United States Pharmacopoeia, or any supplement to them
 - Intended for use in the diagnosis of disease or other conditions, or in the cure, mitigation, treatment or prevention of disease, in man or other animals
 - Intended to affect the structure or any function of the body of man or other animals, and does not achieve any of its primary intended purposes through chemical action within or on the body of man or other animals and does not depend on metabolic action to achieve its primary intended purposes.

The key, and common, part to all of these is the use of the device in diagnosis, monitoring, and treatment of a disease.

Regardless of the user of the device, regulation exists. Medical devices such as syringes, contact lenses, condoms, and bandages are all available to the public, and regulated (at least in Australia). If the same rule that is being proposed for apps was applied for these devices, anyone could make devices such as bandages, and the public would have no guarantee as to the quality, safety, and efficacy of these devices.

Devices and medicines are regulated to protect patients (and the general public) from faulty or harmful devices and drugs, and misdiagnosis or mistreatment from inaccurate information being provided to medical professionals who need to make decisions on the basis of that information. The consequences for patients from medical misdiagnosis from a medical app can be a lot more severe than (lets say) the physics calculations not accurately representing gravity in Angry Birds. Death or permanent disability is a real possibility with inaccurate (or just plain wrong) information being captured by medical apps and used for diagnosis.

Getting a medical device approved can be a very costly exercise. Typically, trials with verifiable data are required to show accuracy and stability in the product. There is also the paperwork required to submit the device to the health regulator in a country, and this submission process needs to be repeated for each health regulator in each country you want to sell your device in.1 However, due to the high cost (and high barrier to entry2 in the marketplace), if you can jump through the regulatory hurdles, you may find a relatively competition-free market. That’s the reward for navigating the processes.

There is also a comment in that article that “Developers are mystified by the rules in this highly regulated industry”. If this is the case, maybe developers need to do the same as other players in the health industry and either employ, or contract in, medical regulatory professionals. Mystification is no excuse for not playing by the rules.

Ignorantia juris non excusat.

Need help?

happtic (my company) provides consulting services related to health regulations for medical apps. If you’re looking for help determining if an app would be considered a medical device, help with understanding regulatory processes, or help with regulatory submissions please get in touch.

  1. Unless you’re in the EU. There is a single health agency for Europe.

  2. Regulatory requirements are only one significant barrier to entry in certain industries. Other industries (such as telecommunications and energy suppliers) also have a large infrastructure requirement requiring both capital investment and significant time. Medical Apps don’t typically have this barrier.

DRYing Out Objective-C - Identification

| Comments

I have a large objective-c codebase I’ve been working on with a client for over a year now. The application started off as a prototype, and transitioned into a demo client, and is currently undergoing modifications for security/penetration testing and commercialization. Initially for the protoype and demo, the objective was to get a working application as quickly as possible – speed of initial development was the key. With the current change in focus to a more productized codebase, and improving maintainability as part of that, I decided I’d actively go hunting for areas in the application that can be tidied up, and particularly, looking for duplicate segments of code and eliminating them where feasible.

DRY – or Don’t Repeat Yourself – is (according to Wikipedia) a principle is stated as “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.”When the DRY principle is applied successfully, a modification of any single element of a system does not require a change in other logically unrelated elements. Additionally, elements that are logically related all change predictably and uniformly, and are thus kept in sync.

One big problem with a larger code base that has been developed over a long period of time is that you may not know where the duplicate code actually is. You know it’s there, you’re just not sure where.

Finding Duplicate Code

What I wanted for DRYing up the code base was for duplicate chunks of code to be identified for me.

Searching out there I stumbled across a project called Simian – it’s a java based tool for identifing duplicate code in a set of different programming languages – one being Objective-C. Simian supports output in a number of different formats – plain text being the default, but also supports an XML based output. The project is available on a 15 day evaluation period, and then should be paid for commercial or enterprise use. A Build Server license costs $499 US.

Simian can be run against a codebase just by feeding it include/exclude directory and file patterns.

java -jar simian-2.3.33.jar -excludes=\"External Libraries\" **/*.m **/*.h

You can also change the format of the output

java -jar simian-2.3.33.jar -formatter=xml -excludes=\"External Libraries\" **/*.m **/*.h

And even output to a file

java -jar simian-2.3.33.jar -formatter=xml:simian.xml -excludes=\"External Libraries\" **/*.m **/*.h

Integration with Jenkins

I’ve previously written here about setting up and using Jenkins as a build/CI system with Objective-C/iOS projects, and I really wanted to integrate this duplicate code reporting as part of my standard build process, along with my unit and application test reports.

To get Simian reports integrated with Jenkins there is a Jenkins extension available called the DRY Plugin. Just navigate to your Jenkins instance and click… Manage Jenkins –> Manage Plugins –> Available and type Duplicate in the filter box. The plugin is called “Duplicate Code Scanner Plug-in”. Install it.

To get the Simian process running is really simple. I added a new project that I could trigger after my unit tests have run, called “Code Analysis”. This project has a very small number of steps.

  1. Pull the source from your code repo
  2. Set a Build Trigger for the project to start after your unit test project has completed. This step isn’t necessary, but you need some sort of build trigger. I like mine to work after unit tests as then I know the codebase is in a good state.
  3. Add an Execute Shell task. The task should look something like below
1
2
3
4
5
6
7
8
cd "<Path to your Jenkins project>/workspace"
git submodule update --recursive --init
echo "#!/bin/bash" > simian.sh
echo "java -jar <Path to your simiar jar>/simian-2.3.33.jar -balanceSquareBrackets=true -formatter=xml:simian.xml -excludes=\"External Libraries\" **/*.m **/*.h" >> simian.sh
echo "exit 0" >> simian.sh
chmod u+x simian.sh
./simian.sh
rm simian.sh

What the above task does is change directory to the correct jenkins workspace, ensure all submodules are updated (if you don’t use submodules, you probably won’t want this), then create a shell script that runs Simian and exits with a 0 return code, sets the script to be executable, runs the script, then cleans up after itself. The reason why the build task needs to create a shell script to run Simian is because the return code from Java/Simian seems to be interpreted by Jenkins as non-0 i.e. a build failure. You don’t want that.

The -balanceSquareBrackets=true flag to Simian ensures that code that is split across multiple lines inside square brackets is treated as a single unit. It might be a good idea to use the -balanceParentheses=true flag as well to help matching on things like if statements.

Then it’s just a matter of configuring the reporting. If you’ve installed the DRY plugin correctly, you should be able to add a Post Build Action of “Publish duplicate code analysis results”. In the “Duplicate code results” field, type in the path and filename you gave the output XML from simian – in the example above I called mine simian.xml.

That’s it.

Save and “Build Now” your new project, and after this is complete, click on the project. There should be a fancy trend graph showing Duplicate Code in the upper right of the screen, and a “Duplicate Code” item on the left navigation menu. That will show you all the files with duplicate code chunks, and the other files they are repeated in.

The Value of Contracting

| Comments

Very unexpectedly, for the past few weeks I’ve been working with a Digital Agency here in Melbourne on a sports-themed iPhone app for a very large client of theirs (a worldwide media brand). I was called in at the 11th hour to work with two other developers (both experienced iOS and ruby contractors), and I knew within the first hour there that the project was going to be a significant challenge. The project had unrealistically tight timelines and a lack of testing and testing platforms/data sets available.

Needless to say, it was an interesting experience. In my previous full time jobs I’ve never worked as a developer, and with my current company all projects to date have been single developer projects. But I definitely found the whole experience really rewarding. It reminded me of the time I was a manager in a large digital agency myself, only there it was me cracking the whip to get development in on time, rather than having the whip cracked on me. :–) (It also meant I had to get dressed and leave the house to work!)

In all seriousness though, the key thing that made the whole thing worthwhile was seeing a “production” codebase from other experienced mobile app developers. My Objective-C design and style is self-taught. It was great to have what I do and the way I do it validated by others, as well as picking up hints and tips for more modular app implementations. This is something that you really miss out on as an indie developer with a one person development team. The shared learning and ability to bounce ideas off people to come up with great solutions is something that is really missing from the indie way of working.

I’ll definitely consider doing more contracting work in the future – both for meeting other developers and for picking up new skills. Highly recommended.

99 Problems (but Haskell Ain’t One)

| Comments

Back in the late 90’s I took COSC 122 at the University of Canterbury. We had to learn functional programming as part of that course – HUGS (it’s based on Haskell 98). It never really clicked with me – for some reason my brain would just not understand functional programming.

I’ve always regretted that I never “got it”. It’s time to fix that regret.

To (re)learn Haskell, I’m using Learn You a Haskell for Great Good!, and to ensure that I “get it”, I’m working my way through the Haskell 99 Problems.

Follow my progress on Github at https://github.com/rickerbh/99-Problems

Updating a UITableView Without Calling reloadData

| Comments

For a new app I’ve been working on for the past few days I wanted to a nice “inline” way of gathering data from the user. Typically, if I’ve needed to have a user put in more than a single line of text, I would have popped the user to a different screen that has a UITextView as the sole point of focus, get them to type in the data, and then have them navigate back and have the data appear within a tableview.

For this new app, I wanted them to be able to enter large amounts of text inline within a cell of a tableview. This also means that the cell would have to dynamically grow and shrink, as the user is entering the data. The UITextView (where the user is entering the data) would need to resize itself based on the users input, as well as the UITableViewCell that contains the text view, and have the UITableView adjust on the fly to the users input.

What I needed to happen was for the UITableView to go through the process of querying the height of each of the cells via the UITableViewDelegate’s tableView:heightForRowAtIndexPath: method, and executing the necessary layout code to push/pull the cells around as an individual cell expands or shrinks. The other complication is that the UITextView that the user is typing in cannot lose focus (i.e., it cannot resignFirstResponder). The obvious way to get the UITableView to perform layout is to call [tableview reloadData], however, this causes the UITextView to lose focus, and the keyboard disappears. This seems to happen when creating the cells via the tableview:cellForRow:atIndexPath: method.

Then I found a sneaky trick.

If you execute the following code the table view will query the height for the individual cells, and lay them out, but not reload the cells, and not cause the UITextView to resignFirstResponder.

[tableview beginUpdates];
[tableview endUpdates];

So, now I have cells that can grow and shrink dynamically, and not lose focus for the user as they are inputting data.

Core Data Migrations and Large Data Sets

| Comments

I recently updated Moving Van (you should buy it now!) and published the new version in the app store late last week. It was a substantial update to the application – it had a completely new UI with custom interface controls, as well as a whole stack of features that customers had been asking for – things like room autocompletion, saving images to camera roll, more export options, moving items between boxes etc.

As part of this update, I also remodelled the Core Data entities that power the application. The initial model that was used was, let’s say, a little naïve in terms of the way that the stored data would impact performance of the application. It stored an image on an item as binary data within the Item entity itself, which in retrospect was a terrible idea because of table view performance. The new version split out the image to a separate entity, which means that when the Item entity loads, the image doesn’t get loaded unless explicitly needed because of the faulting behaviour of Core Data and entity relationships.

So, to get out of this historic design decision, a data migration was required. The migration itself was relatively simple, with pretty much everything working from a standard mapping model (add two entities, copy existing entities, create relationships with new entities). I had to use a custom migration policy for one aspect of the migration – two image entities are created for each item (for tableview performance reasons). There is the original image, and a thumbnail version of that image. The custom policy needed to take the original image from the source Item, scale the image down, and set it in the new Thumbnail entity, but that itself was relatively simple.

The migration was tested with all possible permutations of the data that a user could create, including a large data set with over 100 boxes and hundreds of items. The migration would take a few seconds to run, and everything was working well. I submitted, and released the new version.

DISASTER.

It appears that my data sets for testing were inadequate. Quite a few users of the application store images for every one of their items. 300, 400 of them. Some users don’t even use the text descriptions for items, they just use images. The larger data sets used for testing were text only – none of the testing involved hundreds of items with images. A database with around 500 images is about 300Mb – I think that’s quite a large CD store for the iPhone.

What was happening is that Core Data, while doing the migration, was choking trying to load all the Item entities (with images embedded) into memory. The lightweight migration mechanism seems to try to be fast, over being resource efficient. On the iPhone this is a bad thing if you have a large volume of data – your application will be terminated with little to no warning.

Apple have specific recommendations for what do with large core data sets – mainly around splitting a lightweight migration into separate mapping models. This approach is fine if you have a large number of entities, but it a useless strategy if you have a large number (or more precisely, a large data volume) of an individual entity. Their “chunks” of data refer to a per entity chunk – the approach still attempts to load all instances of an entity into memory. What I needed was a way to have multiple “chunks” of a specific entity, so the whole set was not loaded into memory at once.

The approach I took to solve this problem is very “manual”. It consists of the following steps:

  1. Determine if a migration is required – if so, pop a migration controller that informs the user a migration is taking place, and start the migration.
  2. Create a Core Data stack with the “old” model, and old version of the store as a source.
  3. Create another Core Data stack with the “new” model, and a new store as the destination.
  4. Request a set of entities from the old data store, with a small batch size to avoid loading all entities at once.
  5. Traverse the object graph of those old entities, creating each instance of an entity in the new data store.
  6. Save the new store every 10 or so entities – this is to ensure that the NSManagedContext doesn’t consume too much memory with unsaved objects hanging around.
  7. After this is all finished, backup the original data store, and move the new one to take its place.
  8. Finally, post a notification for the AppDelegate to receive, that signals the migration is complete and the rest of the startup sequence can continue.

The approach works – the application no longer runs out of memory on migration. However, the mapping model is now useless as it’s never used, and there are a couple of interesting points. First one is that the migration takes up extra storage space as we are creating an extra store with pretty much the same volume of data in it – just laid out differently. I’m not sure if this happens when CD performs a migration – I suspect it is, but what worries me is that if a user is low on space, the migration could cause the disk to fill up. The other thing that I noticed was that the migration is considerably slower that a CD managed lightweight migration. However, it actually works on large data sets, unlike the CD managed lightweight migration, so the positives here outweigh the negatives.

There is probably a way to solve this that utilises more of the Migration classes that Apple provide – specifically subclassing NSMigrationManager – but, I didn’t really have enough time available to figure that out – I needed a fix now.

And now some code.

Determining if your Core Data store needs to be migrated

// See if a database exists to be migrated
NSString *sourceStorePath = <Your source store path in the file system>
if (![[NSFileManager defaultManager] fileExistsAtPath:sourceStorePath]) {
  // Database doesn't yet exist. No need to test data compatibility"
  return NO;
}

// Create a persistence controller that uses the model you've defined as the "current" model
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"<Your models directory name>" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

NSError *error = nil;
NSURL *sourceStoreURL = [NSURL fileURLWithPath:sourceStorePath];
NSDictionary *sourceStoreMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
                                                                                               URL:sourceStoreURL
                                                                                             error:&error];
// Do error checking... Removed from the code sample.
NSManagedObjectModel *destinationModel = [psc managedObjectModel];
BOOL pscCompatible = [destinationModel isConfiguration:nil
                           compatibleWithStoreMetadata:sourceStoreMetadata];
// if pscCompatible == YES, then you don't need to do a migration.

Loading old and new Core Data Stacks

You’ll need to do this twice – just swap out the model name for old/new models and keep the references to the MOCs that are created. Ensure you have a different store path for your new store! For the new model, it’s a good idea to also test if a file exists at the new model location – it could be indicative of a migration that’s previously failed.

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"<source or destination model name>" withExtension:@"mom" subdirectory:@"<Your models directory name>.momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

// Get the store url
NSString *sourceStorePath = <Your source/destination store path in the file system>
NSURL *sourceStoreURL = [NSURL fileURLWithPath:sourceStorePath];

// Use this for source store - ensures you don't accidentally write to the entities
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:1]
                                                    forKey:NSReadOnlyPersistentStoreOption];

// Use this for destination store - makes it writeable
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:0]
                                                    forKey:NSReadOnlyPersistentStoreOption];
NSError *error = nil;
[psc addPersistentStoreWithType:NSSQLiteStoreType
                  configuration:nil
                            URL:sourceStoreURL
                        options:options
                          error:&error];
// Do error checking... Removed from the code sample.
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:psc];
[moc setUndoManager:nil];

Get your entities from your original store, and create them in the new store

You can’t use your entity classes here, everything has to be done via KVC. This is because your entity classes will no longer map to the old model correctly.

NSFetchRequest *oldFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *oldEntity = [NSEntityDescription entityForName:@"EntityName"
                                             inManagedObjectContext:oldContext];
[oldFetchRequest setEntity:oldEntity];
// Set the batch size so we don't attempt to retrieve all the data at once - this is the key to the whole thing!
[oldFetchRequest setFetchBatchSize:10];

NSError *error = nil;
NSArray *entities = [oldContext executeFetchRequest:oldFetchRequest error:&error];
int count = 0;
for (NSManagedObject *oldEntity in entities) {
  // Creating new entity
  NSManagedObject *newEntity = [NSEntityDescription insertNewObjectForEntityForName:@"EntityName"
                                                             inManagedObjectContext:newContext];
  [newEntity setValue:[oldEntity valueForKey:@"someAttribute"] forKey:@"someAttribute"];

  // If your entity has relationships...
  for (NSManagedObject *aRelatedEntity in [oldEntity mutableSetValueForKey:@"someRelationship"]) {
    NSManagedObject *newRelatedEntity = [NSEntityDescription insertNewObjectForEntityForName:@"RelatedEntityName"
                                                                      inManagedObjectContext:newContext];
    [newRelatedEntity setValue:[aRelatedEntity valueForKey:@"someOtherAttribute"] forKey:@"someOtherAttribute"];
  }
  // Save periodically
  count++;
  if (count % 10 == 0) {
    [newContext save:&error];
    // Do some error handling
  }
}
[newContext save:&error];
// Do some error handling
// Migration is complete, if you've traversed all your entities.

When I encountered this problem I couldn’t find any example code for how to do this migration – hopefully this helps someone.

If anyone does know of an alternative (better) way to get around this issue, please let me know in the comments.