Search code examples
iosswiftcore-datacore-data-migration

Int16 backed enum attribute in Core Data entity appears to have incorrect value when passed to a model migration function in a custom migration policy


I am performing a Core Data model migration; in my mapping model custom policy function, one of the passed attribute values passed is incorrect. Why is this?

Background:

My Core Data entity Book has an attribute readState, which has type Integer16. The class corresponding to this entity represents this attribute as having an enum type (other attributes removed for clarity):

@objc(Book)
class Book: NSManagedObject {
    @NSManaged var readState: BookReadState
}

@objc enum BookReadState: Int16 {
    case reading = 1
    case toRead = 2
    case finished = 3
}

This has always behaved as expected in this application.

Situation:

I am performing a migration between two model versions. The two versions do not touch readState. The entity mapping for the Book entity has an attribute mapping (for some other attribute) specified by the following value expression:

FUNCTION($entityPolicy, "currentPageForCurrentPage:readState:", $source.currentPage, $source.readState)

My entity mapping has a custom policy class, as follows:

class BookMapping_12_13: NSEntityMigrationPolicy {

    @objc func currentPage(forCurrentPage currentPage: NSNumber?, readState: Int16) -> NSNumber? {
        // function implementation here
    }
}

Problem:

When this migration is performed on a Book entity with the readState attribute equal to .reading (e.g. 1), the function passes the value 17 for readState!

Debug screenshot showing readState equal to 17

Why is this? Is there some oddity in the way that the enums are stored in Core Data? I'm happy to provide any more details if required.


Solution

  • The entity mapping function signature must use NSNumber, not Int16. E.g.:

    @objc func currentPage(forCurrentPage currentPage: NSNumber?, readState: NSNumber) -> NSNumber?
    

    Then readState is correctly passed as 1. I don't understand why.