Swift: Storing states in CoreData with enums

Core DataSwift

Core Data Problem Overview


I want to store an enum state for a managed object within CoreData

enum ObjStatus: Int16 {
	case State1 = 0
	case State2 = 1
	case State3 = 3
}

class StateFullManagedObject: NSManagedObject {
	@NSManaged var state: Int16
}

The last step would be converting the state var of StateFullManagedObject to ObjStatus for direct comparison, which isn't working for me. For example, I can't use the == operator between and Int16 and the Int16 enum. The compile time error I get is

> Int16 is not convertible to 'MirrorDisposition'

. See the conditional below:

var obj: StateFullManagedObject = // get the object

if (obj.state == ObjStatus.State1) { // Int16 is not convertible to 'MirrorDisposition'
	
}

How can I compare/assign between an Int16 and an enum?

Core Data Solutions


Solution 1 - Core Data

You can declare your enum as @objc. Then it all automagically works. Here's a snippet from a project I'm working on.

// Defined with @objc to allow it to be used with @NSManaged.
@objc enum AgeType: Int32
{
    case Age                = 0
    case LifeExpectancy     = 1
}

/// The age type, either Age or LifeExpectancy.
@NSManaged var ageType: AgeType

In the Core Data model, ageType is set to type Integer 32.

Solution 2 - Core Data

You can extract raw Int16 value with .rawValue property of ObjStatus.

// compare
obj.state == ObjStatus.State1.rawValue

// store
obj.state = ObjStatus.State1.rawValue

But you might want to implement stateEnum accessor for it:

class StateFullManagedObject: NSManagedObject {
    @NSManaged var state: Int16
    var stateEnum:ObjStatus {                    //  ↓ If self.state is invalid.
        get { return ObjStatus(rawValue: self.state) ?? .State1 }
        set { self.state = newValue.rawValue }
    }
}

// compare
obj.stateEnum == .State1

// store
obj.stateEnum = .State1

// switch
switch obj.stateEnum {
case .State1:
    //...
case .State2:
    //...
case .State3:
    //...
}

Solution 3 - Core Data

Xcode 12.5 Swift 5

I am storing the values of multiple Enums in CoreData with CloudKit Database.

There are quite a few precise steps required to get this working correctly. I have set out here what I have learned works well.

Step 1: Define your Enum:

Mark it @objc, public and Int16

@objc
public enum SomeState: Int16 {
    case stateA
    case stateB
    case stateC
}

Step 2: In your xcdatamodeld create an attribute where the Enum value will be stored

The type should be Integer 16

enter image description here

Step 3: In the Data Model Inspector uncheck Optional, and set a default value of 0

This equates to the first index of the Enum.

enter image description here

Step 4: In the Data Model Inspector for the parent Entity, change Class Codegen to Manual/None

enter image description here

Step 5: Create NSManaged Subclass

Click on the Entity name, then from the menu bar select Editor > Create NSManagedObject Subclass. Make sure that the Target is set to your main project. This will create two new files in the project navigator.

MyObject+CoreDataClass.swift

MyObject+CoreDataProperties.swift

Step 6: In the MyObject+CoreDataProperties.swift file change the attribute type from Int16 to your Enum type

extension MyObject {

    @NSManaged public var state: SomeState

}

USAGE:

Setting/updating the value:

myObject.state = .stateA

NSPredicate to search for enum value:

NSPredicate(format: "state = %i", SomeState.stateA.rawValue)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkevView Question on Stackoverflow
Solution 1 - Core DataMark KrenekView Answer on Stackoverflow
Solution 2 - Core DatarintaroView Answer on Stackoverflow
Solution 3 - Core DatarbaldwinView Answer on Stackoverflow