3

How would one transfer an array of managed objects retrieved from Core Data using Swift/IOS via a "fetchRequest", to an array that is "identifiable"?

Example - How to make the "tasks" array "identifiable"

let fetchRequest : NSFetchRequest<Todo> = Todo.fetchRequest()
let tasks = try context?.fetch(fetchRequest)

Background:

  • In SwiftUI using a "List" the array of data you pass to the List needs to be "identifiable".
  • I also note the identified(by: .self) seems to be deprecated.
  • Using (Xcode 11, Beta 5)
  • Currently using xcode's automatic creation of managed objects for the core data entities, so would be nice to stick with this approach

1 Answer 1

3

Use replacement ForEach(Data, id: \.idAttribute)

The feature identified(by: .self) was replaced with the new syntax:

ForEach(filteredGrapes, id: \.id) { grape in
    GrapeCell(grape: grape)
}

Coredata example:

Using a file named ItemStore.xcdatamodeld with an entity ItemDAO defined with Generation=Class Definition enabled and having a String-attribute named title.

Note: One has to Product/Clear Build Folder and afterwards restart Xcode to make Xcode11Beta5 find the proper key path, which seems to be a bug in Xcode11Beta5.

import Foundation
import SwiftUI
import CoreData

class MyItemStore {
    public static func defaultItems() -> [ItemDAO]{
        let store = NSPersistentContainer(name: "ItemStore")
        store.loadPersistentStores { (desc, err) in
            if let err = err {
                fatalError("core data error: \(err)")
            }
        }
        let context = store.viewContext
        let item = ItemDAO(context: context)
        item.title = "hello you"
        try! context.save()
        return [
            item,
            item,
        ]
    }
}

struct CoreDataView: View {
    let items: [ItemDAO] = MyItemStore.defaultItems()

    var body: some View {
        VStack{
            ForEach(items, id: \.title) { (item: ItemDAO) in
                Text(item.title ?? "no title")
            }
            Text("hi")
        }
    }
}

Adding Identifiable via Extension

extension Todo: Identifiable {
    public var id: String {
        //return self.objectID.uriRepresentation().absoluteString
        return self.title!
    }
}

Maintaining CoreData models manually to add Identifiable

There you can add Identifiable as usual, which is not necessary though since an extension can add Identifiable too.

Sign up to request clarification or add additional context in comments.

5 Comments

I've just tried this concept with a core data entity which just has one attribute "title", a string, so I have "id: \.title", however I then get a build error: "type '_' has no member 'title'". (line in question: "ForEach(todoStore.getTodoItems(), id: \.title) { item in")
@Greg Added an example. You may have to restart Xcode for it to find the key path, which sounds like a bug.
did just try this but it didn't help - almost as if it can't pick up the "title" attribute from the automatically generated (that I can't in my xcode project) Todo managed object created from my core data model...(?)
got it - I changed to manually creating the managed subclasses, and saw here that xcode was making the "title" attribute optional, although in the coredata designer it wasn't... it's now picking up the "title" attribute ok
Good that it works now. I think it's more akin to an Xcode bug, since I have to Clear the build folder and afterwards restart Xcode for it to pick up the key path properly. This way Class-Definition generation works for me too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.