使用 SwiftUI ForEach 从 NSOrderedSet 获取字符串值

Getting a String value from NSOrderedSet using SwiftUI ForEach

使用 我可以使用 ForEach 来使用从 CoreData 中的一对多关系创建的 NSOrderedSet,但是我似乎无法访问存储在 Core Data 实体中的字符串属性。

我有两个 CoreData 实体:Client 和 SessionNote。 Clients可以有多个SessionNotes,clientNotes的NSOrderedSet,SessionNotes只能有一个Client。

客户端+CoreDataClass.swift:

public class Client: NSManagedObject {

}

客户端+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?

}

会议笔记+CoreDataClass.swift:

public class SessionNote: NSManagedObject {

}

会议笔记+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?

}

这里是 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.
                    */
                }
            }

        }

    }
}

我试过 Text("\(note.noteText ?? "")") 但它抛出以下错误:

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

当我尝试 Text("\(self.selectedClient.clientNotes!.value(forKeyPath: \SessionNote.noteText))") 时,它抛出以下错误:

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

是否可以为每个 SessionNote noteText 实体显示不同的字符串值?

您可以在 NSOrderedSet 上使用 array 方法并将其强制类型转换为 [SessionNote],因为您知道您将始终存储 SessionNote class到有序集。

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

由于在您希望使用注释的每个地方都需要进行此转换。您还可以在 Client 中添加一个计算 属性 ,它始终为您提供 SessionNote 数组的类型版本。

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

而且,通过这些新变化,您可以 ForEach 变得更好。

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

出于这个原因,我尝试使用正常的 Set 作为核心数据关系。因为它可以被输入并且使得使用 Coredata 变得非常有趣。但是,NSOrderedSet 尽管是无类型集合,但也有其自身的优势。