Getting a String value from NSOrderedSet using SwiftUI ForEach

独自空忆成欢 提交于 2020-01-25 08:34:11

问题


Using this question/answer I am able to use ForEach to use a NSOrderedSet created from a One to Many relationship in CoreData, however I can't seem to access a String Attribute stored in the Core Data entity.

I have two CoreData entities: Client & SessionNote. Clients can have many SessionNotes, the NSOrderedSet of clientNotes, and SessionNote can only have one Client.

Client+CoreDataClass.swift:

public class Client: NSManagedObject {

}

Client+CoreDataProperties.swift:

extension Client {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Client> {
        return NSFetchRequest<Client>(entityName: "Client")
    }

    @NSManaged public var firstName: String?
    @NSManaged public var lastName: String?
    @NSManaged public var id: UUID?
    @NSManaged public var clientNotes: NSOrderedSet?

}

SessionNote+CoreDataClass.swift:

public class SessionNote: NSManagedObject {

}

SessionNote+CoreDataProperties.swift:

extension SessionNote {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<SessionNote> {
        return NSFetchRequest<SessionNote>(entityName: "SessionNote")
    }

    @NSManaged public var date: Date?
    @NSManaged public var noteText: String?
    @NSManaged public var id: UUID?
    @NSManaged public var clientOrigin: Client?

}

and here is ClientDetailView.swift:

struct ClientDetailView: View {

    @Environment(\.managedObjectContext) var moc

    @ObservedObject var selectedClient: Client


    var body: some View {
        Form {
            HStack {
                Text("\(selectedClient.firstName ?? "") \(selectedClient.lastName ?? "")")
            }
            Section() {
                ForEach(Array(selectedClient.clientNotes!.set), id: \.self) { note in
                    Text("This will repeat for the number of notes in the clientNotes NSOrderedSet")
                    /*
                     But instead I want to be able to display the noteText
                     string attribute stored in the SessionNote CoreData entity
                     instead of the above placeholder.
                    */
                }
            }

        }

    }
}

I've tried Text("\(note.noteText ?? "")") but it throws the following error:

Value of type 'AnyHashable' has no member 'noteText'

When I tried Text("\(self.selectedClient.clientNotes!.value(forKeyPath: \SessionNote.noteText))") it throws the following error:

Protocol type 'Any' cannot conform to '_FormatSpecifiable' because only concrete types can conform to protocols

Is there anyway to display the different String values for each of the SessionNote noteText entity?


回答1:


You can use array method on NSOrderedSet and force typecast it to [SessionNote], since you know that you will always be storing SessionNote class to the ordered set.

ForEach(selectedClient.clientNotes!.array as! [SessionNote], id: \.self) { (note: SessionNote) in
    Text(note.text ?? "")
}

Since this casting will be necessary in every places you wish to use the notes. You could also add a computed property inside your Client which always gives you typed version of the SessionNote array.

extension Client {
  var typedClientNotes: [SessionNote] {
    return (clientNotes?.array as? [SessionNote]) ?? []
  }
}

And, with these new changes you can make your ForEach bit better.

ForEach(selectedClient.typedClientNotes, id: \.self) { note in
    Text(note.text ?? "")
}

For this reason, I try to use normal Set for Core data relationship. Because it can be typed and makes working with Coredata so much fun. But, NSOrderedSet has its own advantages despite of being an untyped collection.



来源:https://stackoverflow.com/questions/58983303/getting-a-string-value-from-nsorderedset-using-swiftui-foreach

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!