Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data and custom attribute type

Evening,

I'm trying to build an Entity A with a property x of type T.

T is an enum that I created.


How should I set xcdatamodel to use a custom type for an attribute?

My current set up is:

attribute x, type: Undefined, CustomClass: T.

But I have the error:

x .... core data must have a defined type.

Specific Purpose:

x is a "mood" attribute with 3 different moods possible, that's why I choose the enum.

like image 962
Andrea Miotto Avatar asked Feb 24 '17 11:02

Andrea Miotto


2 Answers

There is a type called Transformable in CoreData that's designed specifically for handling types that are not natively supported.

Basically this type will help you automatically serialize a non supported type to a Data object before storing it in the database, and deserialize it when it is retrieved. This is great for storage, but it can become tricky to implement when it comes to queries (because you queries are now using the raw Data used by the database).


An easier way to implement this is to use a computed property that hides the raw value (which will usually be a String or an Int).

Here is how you can implement it :

enum Mood: String
{
    case happy
    case sad
}

class MyObject: NSManagedObject
{
    @NSManaged private var rawMood: String?

    var mood: Mood? {
        get {
            if let rawMood = self.rawMood {
                return Mood(rawValue: rawMood)
            } else {
                return nil
            }
        }
        set {
            self.rawMood = newValue?.rawValue
        }
    }
}

Remember that when you are adding contraint on a query you need to use rawMood and pass it a String. Core Data has no knowledge of a mood property.

like image 200
deadbeef Avatar answered Oct 02 '22 00:10

deadbeef


There is no need to bend Core Data managed objects to accept enums, especially in this simple case.

Just use a standard String attribute, call it mood and do the enum evaluation and appropriate logic when you read and write to it. This will result in human readable, intuitive code.

Edit: sample implementation

enum Mood: String { case happy, ok, sad }
class Person: NSManagedObject {
    var mood: String?
}

// set
person.mood = Mood.happy.rawValue
// get
let aPersonsMood = Mood(rawValue: person.mood!)
like image 35
Mundi Avatar answered Oct 01 '22 22:10

Mundi