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

Posted

技术标签:

【中文标题】使用 SwiftUI ForEach 从 NSOrderedSet 获取字符串值【英文标题】:Getting a String value from NSOrderedSet using SwiftUI ForEach 【发布时间】:2019-11-21 20:33:59 【问题描述】:

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

我有两个 CoreData 实体:Client 和 SessionNote。 Clients可以有多个SessionNotes,clientNotes的NSOrderedSet,SessionNote只能有一个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?


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?


这里是 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 ?? "")"),但它会抛出以下错误:

“AnyHashable”类型的值没有成员“noteText”

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

协议类型 'Any' 不能符合 '_FormatSpecifiable' 因为只有具体类型才能符合协议

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

【问题讨论】:

试试Text(note as? SessionNote)?.noteText ?? "") 这也有效。谢谢! 不客气Text((note as? SessionNote)?.noteText ?? "") 缺少括号。您可能还对github.com/leodabus/OrderedSet 感兴趣 【参考方案1】:

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

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 尽管是一个无类型集合,但也有自己的优势。

【讨论】:

谢谢!这样做了。

以上是关于使用 SwiftUI ForEach 从 NSOrderedSet 获取字符串值的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI .onDelete 从 ForEach 获取 var

SwiftUI 中的 @Binding 和 ForEach

SwiftUI:从 ForEach 中删除项目导致索引超出范围

无法在 SwiftUI 中使用 ForEach 和 CoreData 将数据正确传递给模态演示

SwiftUI - 如何限制 ForEach 中显示的对象数量

如果列表行在 SwiftUI 中包含文本字段,则无法从 foreach 中删除元素