Manual Core Data Migrations – Lessons Learned

So, I’ll try to keep this all brief.  In short, as everyone, including Core Data Ninja Master Marcus Zarra, has said:  Avoid heavy Core Data Migrations!

The tools are buggy, the crash bugs difficult to interpret.  I spent 4-5 hours already just sort of shooting at a black box.   So, I hope to share with you the things I learned and what caught me up.  If this is all too brief or out of context in places, it’s because I’m not a tutorial writer, and keep my blog posts quite often so that I can refer back to them.  So please feel free to write me if you need clarification.

I’ll also give the disclaimer that I’m not the most ‘canonical’ of programmers.  So, these are my findings.  I don’t know if they follow best practices, but I don’t think there are any best practices when it comes to this stuff…. otherwise I probably wouldn’t have made this lengthy blog post!


Migration of old data store using an old Core Data model to a new data store with a brand new Core Data model

This documents my personal experience trying to migrate a Data Model I want to retire (i.e. completely separate Core Data Model file) to a brand new data model.

I wanted to move away from my old Objective-C pipeline which involves NSManagedObject subclasses using mogenerator that all have an Objective-C style Namespace and codegen, to a pure Swift version which uses the codegen feature of the Latest Xcode Core Data editor.

I kept these models separate because in a few releases when I know everyone has upgraded, I can eventually just remove the legacy model from the bundle and all the associated classes.

What I learned / experienced:

  • How to set up incremental migrations using a handy little helper from
  • How to migrate old data to new using Mapping Models
  • How to write and use custom NSEntityMappingPolicy objects
  • How to use the Mapping Model editor to call functions on these custom policies
  • All the various Pitfalls, Gotchas, and things that Apple really needs to improve on.

Useful Pre-requisite Reading:

How to set up incremental migrations

This is really what you want to do.  It makes your life easy in that you only need to make mapping models for each change to your data model.  There is a lot of code floating around the internet that helps you make an incremental migration manager.  I took one from and then modified it so it could support my use case where I am migrating a completely different store to a new one, and that new one should have its own URL on disk that may not follow from the original store.

Code for that migration manager can be found in a gist here.  Don’t just copy-paste:  You have to copy-paste into the correct files!  Also, it’s in objective-c so you’ll want to make a bridging header… It’s really not hard.

What is different in my version of MHWMigrationManager than from on

  • It has a hack fix for a dubious migration error that has minimal debug help: ‘Mismatch between mapping and source/destination models’
  • It allows you to specify via the delegate a “Final Destination URL” once the Migration has successfully completed.  This can be useful as in my case where I have 2 different Stores and Models and want them to stay that way.

Set up your Core Data Stack

Basically, you start with Apple’s boilerplate code for Core Data and a persistent container, then you modify in a way that I’ve done here.  These 2 gists I’ve provided are all just starting points.  We haven’t even got to the annoying stuff yet.

If you create a brand new data model like I have done, be sure that it uses a different name than your old one.  You can’t rename the old one because you want the new one to have the same nice name.  Leave everything about the old one in place.

Pro Tip:  If you didn’t do this but already did the work of creating this new model version, if you create a new model either via duplication or copy-paste of entities, keep in mind that delete rules are not copied over, NOR are the inverse relationships.  So you’ll have to go through and set these by hand again.

Now Create Mapping Models

You can now proceed to create a mapping model in the ways you’ve probably read about on the internet already.   Pro Tips:

  • Only write your mapping model, once your Core Data Object Model is complete.  If you make a modification to your Core Object Model (.xcdatamodeld), any mappings that reference it will no longer be found by the Migration Manager.
  • Due to the nature of the migration process, you won’t have access to any subclass of NSManagedObject, and so this can make setting up NEW relationships difficult.  It is therefore a good idea to keep ‘foreign keys’ on your models with relationships.  (i.e. you extend your Post model to have an Attachment.  Attachment should have an attribute postId, or something identifiable)
  • If you use a subclass of NSEntityMigrationPolicy and you specify it in the Mapping Model editor, make sure that you also provide the Module name.  So, instead of LegacyToModernPolicy, I would put SongbookSimple.LegacyToModernPolicy, because my app’s module name is SongbookSimple.

Mapping Models are useful in that they allow a lot of customization, and you can sort of elect what you want to be done “automagically” and what you’d like to have more control over.  You get more control over these by using custom subclasses of NSEntityMigrationPolicy.

In general, for property or relationship mappings, the auto-generated functionality can get you pretty far.  Otherwise, when you have specified a custom Policy, you can make method calls on that policy.

When to use custom policy methods

If you have a somewhat strange migration for a specific entity, you can just remove all Attribute mappings in for an Entity Mapping, then in your subclass, override the method below.  The method signature is misleading because you are actually asked to create the equivalent version of the old object in the new object.  So you’re manually specifying how one object “becomes” the new object, and in my case where a Song started to store its data in a separate SongData object, you have to create this SongData object and find a way to link the two (i.e. songFilename) because you create the actual relationships later.  EDIT:  What I’ve learned however is that ideally this createDestinationInstances(…) method should really be about 1:1 mapping.  If your migration ends up taking one object and splitting it into two, you should write to Policy Subclasses and have 2 Entity Mappings:  i.e OldSong -> Song and OldSong -> SongData, then in the 2nd pass of the migration where the relationships are re-established, that’s where you can associate them again.

    override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
        let dInstance = NSEntityDescription.insertNewObject(forEntityName: mapping.destinationEntityName!, into: manager.destinationContext)
        let text = sInstance.value(forKey: "text") as! String?
        dInstance.setValue(sInstance.value(forKey: "lastModified"), forKey: #keyPath(Song.createdAt))
        dInstance.setValue(sInstance.value(forKey: "lastModified"), forKey: #keyPath(Song.updatedAt))
        dInstance.setValue("txt",                                   forKey: #keyPath(Song.fileExtension))
        dInstance.setValue(sInstance.value(forKey: "filename"), forKey: #keyPath(Song.filename))
        dInstance.setValue(sInstance.value(forKey: "firstLetterUppercase"), forKey: #keyPath(Song.firstLetterUppercase))
        dInstance.setValue(sInstance.value(forKey: "name"), forKey: #keyPath(Song.title))
        dInstance.setValue(sInstance.value(forKey: "oldFilename"), forKey: #keyPath(Song.oldFilename))
        dInstance.setValue(self.songDataLengthOfText(text), forKey: #keyPath(Song.songDataLength))
        dInstance.setValue(text, forKey: #keyPath(Song.text))
        dInstance.setValue(SongDataType.plainText.rawValue, forKey: #keyPath(Song.typeRaw))
        dInstance.setValue(nil, forKey: #keyPath(Song.userInfoData))
        // NOTE: DON'T DO THIS.  Set up a OldSong -> SongData entity mapping!
        // Then fetch this instance later via its songFilename
        //let songData = NSEntityDescription.insertNewObject(forEntityName: SongData.entity().name!, into: manager.destinationContext)
        //songData.setValue(sInstance.value(forKey: "filename"), forKey: #keyPath(SongData.songFilename))
        //let structure = SongDataStructure()
        //structure.set(text: text)
        //songData.setValue(structure.serialize(), forKey: #keyPath(SongData.nsdata))
        // NOTE: DON'T DO THIS.  Set up a OldSong -> SongViewPreferences entity mapping!
        //let viewPreferences = NSEntityDescription.insertNewObject(forEntityName: SongViewPreferences.entity().name!, into: manager.destinationContext)
        //viewPreferences.setValue(sInstance.value(forKey: "filename"), forKey: #keyPath(SongViewPreferences.songFilename))
        manager.associate(sourceInstance: sInstance, withDestinationInstance: dInstance, for: mapping)

I will say this:  this method above is used to create instances.  You don’t associate them yet!  That’s why you can see I set songFilename on these 2 new data types (in my new model), so that I can create their relationship later…  this is for the second pass in the migration, where relationship mappings are created (more on that).

Quick Reference for Mapping Editor FUNCTION arguments:

NSMigrationManagerKey: $manager
NSMigrationSourceObjectKey: $source
NSMigrationDestinationObjectKey: $destination
NSMigrationEntityMappingKey: $entityMapping
NSMigrationPropertyMappingKey: $propertyMapping
NSMigrationEntityPolicyKey: $entityPolicy

If I don’t need such a detailed mapping of an object, I can also use custom methods to set a property in the editor for any attribute.  Pro Tip: Make sure you change the the “Source Fetch” on a Relationship mapping to “Use Custom Value Expression” if you do this.

FUNCTION($entityPolicy, "filenameForLibraryWith:" , $manager)

This is syntax in the editor.  It’s saying “to get the value for this destination attribute, call a method on the (custom) policy called

func filename(forLibraryWith manager: NSMigrationManager) -> String

Remember you can use the arguments listed about in the Quick Reference section for knowing what kind of arguments you can pass into these methods!

You can also use these custom methods when performing relationship mappings.  Now, I personally haven’t had to override the method:

func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws

I’ve got by with the Relationship mappings in the Mapping Model editor and custom methods.

Do not reference subclasses of NSManagedObject during migration!

It would seem that this is how Core Data ensures that the migration can work reliably.  It sucks because you need to remember:

  • awakeToInsert is not called, because no instances of your subclass are used in migration, so whatever you would set in awakeToInsert, you should do here too.
  • The relationship accessors aren’t present either.  So be safe and specify the relationship and its inverse.

I created a handy helper method to find NSManagedObject instances:

class LegacyToModernPolicy: NSEntityMigrationPolicy {
    static func find(entityName: String,
                     in context: NSManagedObjectContext,
                     sortDescriptors: [NSSortDescriptor],
                     with predicate: NSPredicate? = nil,
                     limit: Int? = nil) throws -> [NSManagedObject] {
        let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: entityName)
        fetchRequest.predicate = predicate
        fetchRequest.sortDescriptors = sortDescriptors
        if let limit = limit {
            fetchRequest.fetchLimit = limit
        do {
            let results = try context.fetch(fetchRequest)
            return results
        } catch {
            log.error("Error fetching: \(error.localizedDescription)")
            throw error

Pitfalls, Gotchas, Other Tips, Things I’ve already said

Here’s a list of things I might have mentioned already, but in this modern age where attention spans are low, and we need headings to actually read something, here is a list of things that I discovered in this long journey over 2 days:

    1. If you created your new Data Model and it started with the same name as your legacy one (i.e. SongbookSimple), it’s better to just create a new Core Data Model file with a new name (e.g. SongbookSimpleDataModel), then rebuild your data model by hand. This in practice means copy-pasting all the entities from the one to the other. Note! The Delete rules are not copied over, NOR are the inverse relationships. So you’ll have to go in and for each Entity, connect these up again.
    2. If you get an error during Migration such as:
      Couldn’t create mapping policy for class named (LegacyToModernArtistPolicy)
      It’s probably because you have Swift module-related errors. See Sandeep’s comment in this Question:
      So LegacyToModernArtistPolicy becomes SongbookSimple.LegacyToModernArtistPolicy and it works
    3. If you change your current model to accommodate the migration process, AND you’ve already run the app, you’ve altered the data model in a bad way. You don’t know if this is a typical state to be in, so better play it safe. You’ve got to remove the app from the simulator, re-install an old version so to populate an old data store, then run your new version in development.
    4. If you are doing custom fetch requests so to satisfy creating relationships (in your NSEntityMigrationPolicy), it would seem that fetch requests are returning NSManagedObject objects and not the subclasses. Nor can they be casted. For example, you might have seen a crash error:Could not cast value of type 'NSManagedObject_Library_' (0x6100000504d0) to 'SongbookSimple.Library' (0x101679180).This is why the helper above can be useful.  I fixed the bug I mention here with:
          func libraryForManager(_ manager: NSMigrationManager) -> NSManagedObject {
              do {
                  var library: NSManagedObject? = try LegacyToModernPolicy.find(entityName: Library.entity().name!,
                                                          in: manager.destinationContext,
                                                          sortDescriptors: [NSSortDescriptor(key: "filename", ascending: true)],
                                                          with: nil,
                                                          limit: 1).first
                  if library == nil {
                      let dInstance = NSEntityDescription.insertNewObject(forEntityName: Library.entity().name!, into: manager.destinationContext)
                      // awakeFromInsert is not called, so I have to do the things I did there, here:
                      dInstance.setValue(Library.libraryFilename, forKey: #keyPath(Library.filename))
                      dInstance.setValue(NSDate(timeIntervalSince1970: 0), forKey: #keyPath(Library.updatedAt))
                      library = dInstance
                  return library!
              } catch {
                  fatalError("Not sure why this is failing!")
    5. You think you are far along because all of your NSEntityMigrationPolicy objects are having their custom methods called, nothing is failing, but at the end of the migration process you’re still getting errors. SpecificallyCocoa error 1570. This implies that data validations are failing.It could easily be that it’s because you made a false assumption that awakeFromInsert will get called on your new instances during the migration process. For example you added a non-optional attribute to your model who gets his default value set in awakeFromInsert. You should specifically make sure these are getting set either via the mapping editor and your custom policy (with a custom method), or try to handle the errors in performCustomValidationForEntityMapping:manager:error:I prefer graphic tools. So I just write some boring methods that will set default values and it’s all good.
    7. In all of the NSEntityMigrationPolicy subclass, make sure you are always dealing with NSManagedObject and not their subclasses!! If you don’t, your automatic mappings (that use custom methods on the policy subclass) will fail.
    8. You don’t HAVE to create mappings in the Mapping Model editor. Basically, the part that has attribute mappings is a way of NOT overriding the method
      func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws

      and the Relationship Mappings editor is a way of not having to subclass

      func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws

      ONE THING you DO need to understand is that during the migration process, you are dealing with NSManagedObject instances, and not instances of your (likely) subclasses. So you don’t get all the benefits of the accessor methods that would ensure object graph integrity. What does this mean? You should make sure that you connect both sides of a relationship via relationship mappings. This means, in your data model it makes sense to keep a field to a ‘primary key’, so that you can use one object to find another.

    9. YAY! The Migration manager says it migrated… except… I got an exception:
      'Mismatch between mapping and source/destination models'

      I have to say, Core Data documentation sucks. There’s just not enough of it, and no explanation of why it fails during migration. Totally crap. I’ve spent a whole day just trying to shoot into the dark, hoping I’ll figure out what’s going on with this giant black box.

      The fix for this occurs in my modified MHWMigrationManager gist, and it’s what sorted me out!

Still Missing from everything that I learned:

  • I don’t really know how one is supposed to work with the createRelationships(…) method.  I only do that aspect of migration via the Mapping Model Editor and custom methods on the Policy
  • I haven’t done anything with validation yet.  So I don’t know how that comes into play.

Wrapping Up

This was a super long post.  But hopefully it can be seen as a good reference guide or at least things to think about when trying to do heavyweight migrations.  Now that I understand how they’re done, they’re not AS scary anymore.  What was annoying was trying to figure this all out.

If you benefit from this, I would be happy if you let me know!


Useful “Finder” methods on NSManagedObject in Swift

I don’t know about you, but CoreData seemed insane to me before I discovered MagicalRecord, back in the days of Mogenerator and Objective-C.

But since Swift 3 has come out, and the tools have improved to support Swift development (remember poor compiler warnings, if not just a “segmentation fault 11” error), I’m finding that I like to work with the Xcode tools again, and forego these old approaches.

My old way of doing things worked very well, and in some ways I miss some aspects of that, but ultimately I quickly (swiftly… cough cough) became a lover of Swift and simply prefer developing in that language.

What I miss most were the “MagicalFinders” categories present in MagicalRecord.  I found quite a concise way to do that however in Swift, and the code looks like this:

import Foundation
import CoreData

@objc public protocol CoreDataFinders {

    /// Because we are doing fetch requests on a data model,
    /// Fetch requests require sort descriptors.
    static func defaultSortDescriptors() -> [NSSortDescriptor]

extension CoreDataFinders where Self: NSManagedObject {
    public static func findAll(with predicate: NSPredicate?, context: NSManagedObjectContext) -> [Self] {
        let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: Self.entity().name!)
        let predicate = predicate
        fetchRequest.predicate = predicate
        fetchRequest.sortDescriptors = self.defaultSortDescriptors()
        do {
            let results = try context.fetch(fetchRequest)
            return results
        } catch {
            if predicate != nil {
                print("Failed to fetch objects with predicate:\(predicate!.description) error:\(error)")
            } else {
                print("Failed to fetch objects with no predicate.  error:\(error)")
        return []
    public static func findFirst(with predicate: NSPredicate?, context: NSManagedObjectContext) -> Self? {
        let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: Self.entity().name!)
        let predicate = predicate
        fetchRequest.predicate = predicate
        fetchRequest.sortDescriptors = self.defaultSortDescriptors()
        fetchRequest.fetchLimit = 1
        do {
            let results = try context.fetch(fetchRequest)
            return results.first
        } catch {
            if predicate != nil {
                print("Failed to fetch objects with predicate:\(predicate!.description) error:\(error)")
            } else {
                print("Failed to fetch objects with no predicate.  error:\(error)")
        return nil

And then you can add these to any object by either making a new baseclass in your app that subclasses NSManagedObject, or you just declare protocol support in your class definition and then these methods are added:

import Foundation
import CoreData

class RecentItem: NSManagedObject, CoreDataFinders {
  static func defaultSortDescriptors() -> [NSSortDescriptor] {
    return [NSSortDescriptor(key: #keyPath(RecentItem.lastViewed), ascending: false)]
  // ...

You can see here that you can extend this approach to pass in your own sort descriptors or limit fetch sizes, etc. This should be enough to get you started! The idea is that you can write the code once and have it apply to all instances of NSManagedObject on an opt-in basis.

Today was the first day that Test Driven Development actually justified its existence

I’ve been making apps since iOS 2.2.  People tell me I’m good at it.  Meh.  There’s always a bigger fish.  I love what I do, so chances are I’m not horrible at what I do.

Today was the first day where I used Test Driven Development to actually develop code.  Don’t get me wrong; it’s not like I don’t write unit tests.  I do.  But what I’m referring to right now is where you actually are given the start and passing conditions of a test before there is any code written at all.  In my field of work, this never happens.  The design is ALWAYS a moving target.  Nothing in the startup world is ever known in advance, so although you could write unit tests, it doesn’t always make sense.

I’ve recently been working on the implementation of the rules of Canadian Ice Hockey.  (Don’t ask.)  The sport itself seems pretty straightforward.  Put the puck in the net.  Goal.  Increase Score.  No way!  There are a lot of complicated rules surrounding penalties, but thankfully there is a referee’s handbook that goes over all the complicated scenarios and tells you what the result should be.

Perfect for TDD.  I literally wrote all the unit tests before I wrote the code that would produce the expected results.  I love it because I have to be honest; the solver code I wrote just “feels bad”.  I’m not even certain how parts of it work, and I only wrote it this past week.

What unit tests tell me is: It doesn’t matter!  As long as the tests pass, the code does what it’s supposed to do.  Very satisfying.


What I miss about Objective-C

Don’t get me wrong; I love Swift and it’s my preferred language.  It really didn’t take long to love it.

That being said, I really miss the idea of protected and private declarations, and creating Category Headers to expose private API’s.

It’s like giving a class “special permission” to interact with the private API’s of a different class, if there are a few classes that operate more closely, but still limiting the exposure of some properties to objects that aren’t coupled as tightly.

In Swift you just expose them all and write comments I guess.  Perhaps I’ll figure that out when I become more experienced with Swift.

DataSource object for UITableView / UICollectionView in Swift with Core Data

It’s amazing how quickly I now have become a part of the Swift Fan Club.  I recently worked on some old Objective-C code of mine and was amazed how quickly one learns to stop typing semi-colons.  🙂

Today’s post is all about a pattern I use more often in my projects, and it’s one that prefers composition over inheritance.  All that really means in this case is that on any UITableViewController (or similarly, UICollectionViewController), I prefer to create separate Data Source objects that keep all that code separate from the View Controller itself.  (I personally don’t find that MVC stands for Massive View Controller if you don’t let it.)

The issue here is that I pretty much don’t do projects any more without using Core Data.  It is the best solution in my opinion because of the code you oftentimes *don’t* have to write.  Also, with NSFetchedResultsController, I like how you can further separate your data layer (think Networking and importing) from you View Controllers.  View Controllers concern themselves with *what* they want to display, and not with how it is acquired.

Anyway, the strictly typed language of Swift sometimes makes old approaches not straightforward, and I would like to share what I determined today.  It will become a staple in my future Swift projects.

I create a DataSource class that takes a generic type, so that this generic type can be used for Core Data related activities.  By default, a NSFetchedResultsController also takes a generic type of NSFetchRequestResult. But sometimes that is simply not enough. More on this later. To even make a Generic Data source, we have:

class BasicFetchedResultsDataSource: NSObject, NSFetchedResultsControllerDelegate where T:NSManagedObject {
    let managedObjectContext: NSManagedObjectContext!
    let tableView: UITableView!
    init(context: NSManagedObjectContext!, tableView: UITableView!) {
        self.managedObjectContext = context
        self.tableView = tableView
    private var _fetchedResultsController: NSFetchedResultsController? = nil
    var fetchedResultsController: NSFetchedResultsController {
        if _fetchedResultsController != nil {
            return _fetchedResultsController!
        let request = T.fetchRequest()
        request.predicate = self.searchPredicateForFetchRequest
        request.sortDescriptors = self.sortDescriptorsForFetchRequest
        let controller = NSFetchedResultsController(fetchRequest: request as! NSFetchRequest,
                                                    managedObjectContext: self.managedObjectContext,
                                                    sectionNameKeyPath: self.sectionNameKeyPath,
                                                    cacheName: self.resultsControllerCacheName)
        controller.delegate = self
        _fetchedResultsController = controller
        return _fetchedResultsController!
    func updateRequestAndFetch() throws {
        self.fetchedResultsController.fetchRequest.predicate = self.searchPredicateForFetchRequest
        self.fetchedResultsController.fetchRequest.sortDescriptors = self.sortDescriptorsForFetchRequest
        do {
            try self.fetchedResultsController.performFetch()
        catch {
            throw error
    // allows your subclass to override and change this
    var sectionNameKeyPath: String? {
        return nil
    // allows your subclass to override and change this
    var resultsControllerCacheName: String? {
        return nil
    // allows your subclass to override and change this according to state
    var sortDescriptorsForFetchRequest: [NSSortDescriptor]! {
        return []
    // allows your subclass to override and change this according to state
    var searchPredicateForFetchRequest: NSPredicate? {
        return nil
    // ... Typical NSFetchedResultsController and UITableViewDataSource code here.

That’s it for the basics, but what if my data model is a bit more interesting? In my current project I want my data to be sortable, filterable, searchable, and possibly groupable.

So I define the following:

import CoreData
@objc protocol Sortable: NSFetchRequestResult {
    static func defaultSortDescriptors() -> [NSSortDescriptor]!

@objc protocol Groupable: NSFetchRequestResult {
    var groupIndex: String! { get }

@objc protocol RelationshipFilterable: NSFetchRequestResult {
    static func relationshipFilterPredicate(for constraintObject:NSManagedObject?) -> NSPredicate?

@objc protocol TextSearchable: NSFetchRequestResult {
    static func searchPredicate(for searchTerm:String?) -> NSPredicate?

@objc protocol MyGenericDataObject: Sortable, Groupable, RelationshipFilterable, TextSearchable {
    // combines them

Then the cool stuff. Subclass the Basic view controller above:

class GenericFetchedResultsDataSource: BasicFetchedResultsDataSource where T:NSManagedObject {
    let allowsGrouping: Bool
    let allowsTextSearching: Bool
    override init(context: NSManagedObjectContext!, tableView: UITableView!) {
        self.allowsGrouping = true
        self.allowsTextSearching = true
        super.init(context: context, tableView: tableView)
    var currentSearchTerm: String? {
        didSet {
            if self.allowsTextSearching {
                do {
                    try self.updateRequestAndFetch()
                catch {
                    print("Fetch Error: \(error)")
    override var sectionNameKeyPath: String? {
        return self.allowsGrouping ? #keyPath(MyGenericDataObject.groupIndex) : nil
    override var resultsControllerCacheName: String? {
        return nil
    override var sortDescriptorsForFetchRequest: [NSSortDescriptor]! {
        return T.defaultSortDescriptors()
    override var searchPredicateForFetchRequest: NSPredicate? {
        return self.allowsTextSearching ? T.searchPredicate(for: self.currentSearchTerm) : nil

And that’s how you can work with generics and their subclasses. It’s why protocol oriented programming and swift go together nicely!

How Swiftly I began to love Swift…

So, my last post was a little nasty.  Written like a conservative populist, which politically I’m not, but I admit I had my reservations about learning Swift then, and I stand by that opinion at that time.  I’ll be brief this time.   I’ve now had a chance to really do some work with Swift and I have to say overall I quite like it, and never expected that to happen so quickly.  Why the change of heart, you might ask?

  • I guess I don’t like learning from books, but I like learning by doing.  I find a lot of tutorials out there on the internet kind of superficial and boring.  I joined a project where there was already enough Swift code but not too much.  I had the opportunity to contribute based on some code I could already work from.
  • I really do like a lot of the features, such as enums (and being able to use string types)
  • The syntax is pretty good.  It does make for readable, type-safe code.
  • I’m surprised at how quickly one can just start writing useful code
  • Since Swift 3, there really is no reason to say no to it.  Previously it all felt “too new” and not finished.  The compiler warnings were a total disaster. For a strictly typed language, having poor compiler warnings was the most discouraging aspect to it. (Hence the rant about German bureaucrats who aren’t helpful but just say no)
  • I’m sure other reasons here as well

Now, it’s not like I’ve become blindly religious.  Sometimes I don’t like to the strictly typed language, but I suspect my frustration comes from the typical approach of “well, in Objective-C, I could just…” and not yet knowing the equivalent approach in Swift.

But all in all, I think it’s pretty easy to get up and running and to start writing Swift code that is useful and readable.  I’ve seen some library code that tells me I still have a lot to learn, but for now I think it’s kind of a “no turning back” situation.

I’ve already basically done all the types of things I’ve done in objective-C, and find that I really didn’t use KVO that much anymore anyway, so I don’t miss it.

I thought I’d just round off that last angry post with something nice.

Why I Still Don’t Use Swift in Real Projects

(UPDATE:   My opinion has changed)

So, every so often, when I’m not busy making production apps for clients that have to work, be reliable, be easy to read, be easy to extend, be easy to debug, and so on, I have a look at Swift.  I know I’m admitting something that perhaps one best not admit; I don’t use Swift yet, really.  I haven’t fully embraced it.  And I’ll tell you why.

I’m a creative developer.  Also, I live in Germany.  I therefore hate bureaucracy.  There’s a connection.  Germany for me has at times been a near death experience…. death by 1000 paper cuts.    With Objective-C, and all those Cocoa Frameworks, I know these tools very well.  As a creative developer, I am as interested in the beauty of the project on the outside as I am with the beauty of it on the inside.  I would reckon I’m pretty good at writing Objective-C code.  Obviously because of experience and a commitment to quality.

I understand there’s a learning curve with anything new.  I get that.  I clash with Swift when I have a creative idea and I just want to build the thing I want to try out.  App development is a strange voodoo; you can have a good idea on paper, then once it’s in your hand and you interact with it, it makes that idea perhaps less awesome or less useful than you thought.  So, the ability to do rapid prototyping is of great interest to me.

Enter the strictness of Swift and its compiler.  For me it’s like going to any German ministry to get something done.    You turn up with your form (well, forms) with the hope of getting it stamped and approved today.  They turn you away for some reason.  It’s always some reason.  Sometimes they invent reasons because they don’t like the look of you. The civil servants don’t think creatively nor solution-oriented.   You can’t ask for help.  You only have to state what function you would like them to carry out today.  The number of times they give you that stare as if to say “Invalid input.  Invalid input. Invalid input.” and you expect smoke to start billowing out their ears at any second.  Similarly, the Swift compiler annoys the hell out of me because the error messages are still kind of cryptic, not always referring to the actual error and potential solution to the problem (comparing to Objective-C here… which also loses its way from time to time). Basically “sorry, can’t do it.  Go bother someone else.”

No, I’m a free spirit.  I like the dynamic nature of Objective-C.  I like being able to say “I know this is bending the rules a bit, but please just do it, because I know what I’m doing here.”  and the compiler will do it.  Maybe your code crashes at runtime, but maybe not.  In the end, experience will often have a strong say here.

Say I actually did get my Swift code running.   I’m not an early adopter.  I’m just not.  With any software product, I prefer to sit back and wait, let them iron all the kinks out, then I’ll be interested.  I have too many other hobbies and interests that also take my time, so to want to update my old, running code, because now the language itself has changed and is no longer compatible and I am forced to update it, just so it will run, does not sound like a desirable use of my time.

Then I hear just around 10% of apps in the app store actually have Swift code in them.   People make it seem like if you can’t code in Swift you are massively behind the times and are unemployable because it’s *all Swift* now….

I don’t know, for all these reasons, I still sit back and wait.  I try to keep up on the language in general, but for me I’d just like to say “sort yourselves out, and let us know when it’s ready for general consumption, because right now I don’t like make-work projects.  I just want to build great things, quickly.”  Sitting in front of a cryptic compiler error message because of typing or unwind errors is not my idea of swiftly creating anything at all.