Thrice blessed, Oh Core Data !

I was told to stay as far as I could from Core Data. From what I've gathered, some people hate the poor thing, and others... don't really dislike him ? I guess ?

So, let's add my own little story to this.

Exposition

A few months back, I had an existing database, for an app I had put on the App Store (it's still there by the way). The one and only entity had a few properties, and I had decided I had to add tags.

Rising Action

The Rookie's First mistakes

And there I went merrily, adding an array property to my existing entity, believing with the early believers' faith in Core Data. Sure it was a Transformable property, but who cared ?

I built it, ran it on my one and only device... and lost all my existing data in the ensuing failed non-migration. Oups.[^1][^2]


Rookies don't live long in CoreData's Land - Photo by Casey Allen / Unsplash

Evaluating the damage

Just in case, I tried to check the app's image using an sql editor, to no avail. Everything was somehow gone. I also discovered at the same time that CoreData Editor is now outdated.

Climax

Where we figure out what to do next

First, I wanted to just give up on migrations, remove the current release from the App Store, push the new one and never have to think about it again. After all, nobody had bought it aside from my little brother, right ? Out of caution, I checked, and there it was. Someone in the UK had bought it a week earlier.


I just couldn't let my first, trusting (paid), and only user down. Now, I had to fix it.

Initially looking into Apple's own documentation on the matter, I quickly ran away. As you may have noticed, it is severely outdated.[^3] I did however end up grasping the concepts of model versionning, lightweight migration and heavyweight migration, mostly thanks to a few blog posts, Ray Wenderlich and Stack Overflow (won't list all the answers I went through)[^4].

The answer was quite straighforward: a Lightweight migration

My app's database after my careless update. Photo by Simon English / Unsplash

Falling Action

The Lightweight Migration

Well, I had hoped so. But it appears the you can't do a lightweight migration when adding a new Transformable attribute to a model. So unlike the plane just above, it crashed. Again. At least the plane got to crash only once.

Next thing was setting a default value for the new attribute. People seemed to do it in the GUI. But I couldn't. Because it's a Transformable. Frak. Against my (and pretty much everyone else's) better judgement, heavyweight migration it shall be.

The Heavyweight Migration

That's the Mohamad Ali of migrations. The Hulk Hogan of catch migrations. The... well, you get it. It's supposed to be a monstruous mess. So I went looking for more detailed explanations, guides and resources. Suffice to say, there wasn't as much to find out there.


What the land of Heavyweight Migrations documentation looks like. Photo by Eniko Polgar / Unsplash

More importantly, there wasn't any direct answer as to how to create a new attribute through Heavyweight Migration.

So here it is, at last, the result of an afternoon of searching, reading, and trial and error:

A migration policy

import CoreData

class IdeaToIdeaWithTagsMigrationPolicy: NSEntityMigrationPolicy {

    @objc func createNewTags() -> NSArray {
        return [] as NSArray
    }
	
    @objc func migrate(uuid: String) -> UUID {
        guard let uuid = UUID(uuidString: uuid) else {
            return UUID()
        }
        return uuid
    }
}

And a mapping model


Also, if you want the same eye-bleeding resolution on your own retina mac, check out RDM.
For a cool screensaver that is guaranteed to waste all of your colleagues' time as they stop to stare in awe while they were passing by your desk as you're getting yourself a coffee, see Aerial

Denouement

So, what should we get away from this afternoon ?
Well, first of all... if you personally are (and you should be) a user of your own apps, get a dev device. Really.

Next, figure out a way to backup and restore your and your users data, seamlessly and securely. No matter how hype, backups are and will always be underrated.

Third, know a little about what you are getting yourself into before using something you've never played around with.

Fourth, just because something is Apple's native persistence framework (or anything framework) doesn't make it simple, straightforward, clearly documented and well-maintained. And I'm pretty sure Core Data isn't the worst.

Last, but not least, as a courtesy to your users and fellow developers, extensively and comprehensively document your exposed features and APIs', and keep it up to date ! Damn it.

If you found this post's structure amusing or reminiscent of your Middle School years, check out this wikipedia page on narrative structure.