Making mailing lists nicer: Writing a mail extension for macOS with MailKit

As a developer, I need to work with mailing lists a lot. Developer-focused mailing lists tend to have certain conventions most usage of email has moved on from, as have the clients. While some people who trawl mailing lists configure some terminal email client, I tend to not like those. Most of the time, I use the stock Apple mail application (Mail.app). It otherwise works well and has platform integration.

However, I do want to avoid a lot of common mailing list faux pas, like top posting and not wrapping lines. Mail.app can write plain text emails, but it doesn’t push you in the right direction for mailing lists. However, Mail.app does provide an extension API. I figured I could write an extension to make my life on mailing lists easier. Turns out it’s possible!

The extension I wrote is called MailTools (tentative until a better name is found). Feel free to build or download it yourself; this article explains the challenges I faced.

Continue reading

Updating Core Data object ID URIs on store migrations

I found out recently that Core Data object IDs can change. This usually happens if you migrate a store, such during a heavyweight migration (lightweight migrations don’t count, as they mutate in place). If you were like me and persisting object IDs, then you’ll have to update those URIs, or you will have a very bad day trying to fetch objects from these IDs.

The easiest way to do this is to lean on NSMigrationManager, because it has both the source and destination model versions, and can get the destination object version from the source version. If you’re manually doing the migration for model upgrades, you easily have it already. If you want to update it from a NSEntityMigrationPolicy, then the easiest option is to stash the NSMigrationManager by overriding beginEntityMapping:manager:error:. You provide it the source NSManagedObjects, and out comes the destination version’s managed objects, as shown below, of which you can get the new object IDs to persist in the new version of the model:

var manager: NSMigrationManager!

private func destinationURIsFromSourceObjects(_ objects: [NSManagedObject]) -> [URL] {
    return manager.destinationInstances(forEntityMappingName: "TrackToTrack", sourceInstances: objects).map {
        $0.objectID.uriRepresentation()
    }
}

Note that you need to provide the entity mapping name – regardless if your entities heavily changed or not. For the Xcode mapping model generator, check the name – it’s usually something like TrackToTrack. If you need to get the managed objects from the source version’s URIs, you can use the the sourceContext property in the migration manager to get the source model version’s managed object context.

Dealing with key-based polymorphic JSON in Swift Codables

I’ve been trying to use Swift’s Codable protocol with some data I wanted to decode over the wire. Codable makes it easy to serialize things in Swift. Unfortunately, the schema of the protocol I was using doesn’t cleanly map to something easily represented in Swift. It consists of a single object, with a single key, and the key’s name determining its value and type. For example, various JSON blobs:

{"Chat": {"message": "Hello world!"}}
{"Error": {"message": "Invalid request"}}
{"Hello": {"username": "alice", "version": "1.0"}}
/* there are more, but we'll stick with this set for the example */

How do we decode this cleanly?

Continue reading