saving Int array as attribute in a CoreData entity

I'm embarrassed to say I haven't been able to google this successfully: I'm trying to save a couple of arrays of Int's (Int16 would be more than enough) as some of the attributes of a core data entity. The entity is basically a score box (like a baseball one) and it contains names of each player, and arrays for the number of points scored at each turn, among a few other standard attributes.

I'm pretty sure I need to make the array attributes Transformables. I don't know how to write the transformer. I thought I could maybe do the manual codegen, and then write some code to transform the int arrays into strings? Not sure. I can't imagine I'm the first person to try to tackle this problem, but I couldn't find anything anywhere that had a sample of something related to what I'm looking for.

If anyone could point me to a related resource, I'd really appreciate it.

Also, too, I'm a hopeless newbie.

Answered by Zimmie in 716898022

Core Data has some value transformers already. Set the attribute to be Type: Transformable, and set the custom class to be [Int]. It should work.

Accepted Answer

Core Data has some value transformers already. Set the attribute to be Type: Transformable, and set the custom class to be [Int]. It should work.

hi,

Zimmie is right -- set the Custom Class to [Int]; but three quick things:

  • for your transformable attribute, you will also need to set the Transformer to be NSSecureUnarchiveFromDataTransformerName; you'll otherwise probably get a warning about this at some point.

  • remember that the values you store in a transformable attribute will not be searchable using any sort of fetch request.

  • if you really are a hopeless newbie, i would suggest setting the CodeGen to Class Definition and let Xcode generate the Core Data classes for you, especially if you Core Data model has relationships.

hope that helps,

DMG

Thanks Zimmie, DMG. It did work after adding the NSSecureUnarchiveFromData to the transformer field.

(Shouldn't Xcode have a dropdown with the built-in custom-classes in there? Not very discoverable, otherwise.)

Zimmie, DMG: I have a follow-up if you even happen to see this. I don't think I need to upload the code to ask the question. Let me try.

my try? moc.save() statements (I did change them to do/catch eventually while trying to debug) were in a non-view file where the class dealing with the data that needed to be saved lived, and was transferred to core data through a method part of that class. The class had "@Environment(.managedObjectContext) var moc" in there, and the app compiled fine.

The app did compile, but the data wouldn't save in core data. Eventually I figured out it that the try save.moc spat the error "The operation couldn’t be completed. (Foundation._GenericObjCError error 0.)". Googling that wasn't too productive either, but something I saw made me try to put all of the method code into the appropriate button within the view that called for that method (it's quite a bit of code). That, somehow, worked.

My question: why? It does work, but my code looks even uglier than my usual *****. I would love to move that to the class in a separate file. Thanks a ton.

hi,

@Environment is only available (well, only makes sense) in SwiftUI views. @Environment(\.managedObjectContext) var moc specifically picks out the managed object context in a view's SwiftUI environment -- that context is often created and placed into the SwiftUI environment in the main-level App file.

if you are in some other non-view code, say like a view model object, you would need a direct reference to the managed object context.

example: in Apple's default Core Data project template, it creates a shared global singleton PersistenceController object, and injects its managed object context into the main level ContentView (which is then shared in subviews) by writing

let persistenceController = PersistenceController.shared
var body: some Scene {
    WindowGroup {
        ContentView()
            .environment(\.managedObjectContext, persistenceController.container.viewContext)
    }
}

if this is your situation, you can reference the managed object context anywhere in your code (within view or not) by writing

let moc = persistenceController.shared.container.viewContext

hope that helps,

DMG

Dude, thank you SO much! You saved me days of floundering cluelessly.

I did have PersistenceController injected into ContentView exactly as you describe. For some reason, in the ViewModel I needed to make the "p" capital as in "moc = PersistenceController.shared.container.viewContext". I'm only mentioning this to help another clueless soul like me that might end up looking at this thread.

You made my code way less emetic, and I thank you again for that.

a.

saving Int array as attribute in a CoreData entity
 
 
Q