使用 Core Data 在 SwiftUI ForEach 中为 Data.Element 键入未知数

Posted

技术标签:

【中文标题】使用 Core Data 在 SwiftUI ForEach 中为 Data.Element 键入未知数【英文标题】:Type unknown for Data.Element in SwiftUI ForEach using Core Data 【发布时间】:2020-02-08 00:13:13 【问题描述】:

我正在尝试使用泛型来获取核心数据实体中的所有项目。一切都很好,除非在 ForEach 循环内。

类型未知

在 ContentView 中,我想做类似的事情

FilteredList<Singer>(filterKey: "lastName", filterValue: lastNameFilter)

FilteredList<Baker>(filterKey: "lastName", filterValue: lastNameFilter)

FilteredList<Painter>(filterKey: "lastName", filterValue: lastNameFilter)    

FilteredList<Friends>(filterKey: "lastName", filterValue: lastNameFilter)

这是错误

我可以用(实体为!歌手)修补它

但我失去了泛型的力量

我关注的这段代码来自 Paul 的 Dynamically filtering @FetchRequest with SwiftUI

这是代码...

import SwiftUI
import CoreData

struct FilteredList<T: NSManagedObject, Content: View>: View 

  @Environment(\.managedObjectContext) var moc

  var fetchRequest: FetchRequest<T>

  var entityItems: FetchedResults<T>  fetchRequest.wrappedValue 

  // this is our content closure; we'll call this once for each item in the list
  let content: (T) -> Content

  init(filterKey: String,
       filterValue: String,
       @ViewBuilder content: @escaping (T) -> Content) 

    fetchRequest =
      FetchRequest<T>(
        entity: T.entity(),
        sortDescriptors: [],
        predicate: NSPredicate(format: "%K BEGINSWITH %@", filterKey, filterValue))

    self.content = content
  //init

  var body: some View 
    List 
      ForEach(fetchRequest.wrappedValue, id: \.self)  entity in
        //self.content(entity)
        Text("Hello, World! \((entity as! Singer).wrappedFirstName)")
      //ForEach
        .onDelete(perform: removeAccount)
    //List
  //body

  func removeAccount(at offsets: IndexSet) 
    for index in offsets 
      let oneEntity = entityItems[index]
      moc.delete(oneEntity)
    //for
    try? moc.save()
  //removeTransaction
//FilteredList

struct FilteredList_Previews: PreviewProvider 
  static var previews: some View 
    FilteredList(filterKey: "lastName", filterValue: "A")  (entity: Singer) in
      Text("Hello, World! \(entity.wrappedFirstName)")
    //FilteredList
  //previews
//FilteredList_Previews

【问题讨论】:

【参考方案1】:

您可以尝试使SingerPainterBakerFriend 成为Protocol 的一种类型。

extension Singer: PersonProtocol


extension Painter: PersonProtocol


...
protocol PersonProtocol 
    var wrappedFirstName: String? get set
    var wrappedLastName: String? get set
    ...

这样,当您使用ForEach 方法时,您可以将entity 解包为PersonProtocol

    Text("Hello, World! \((entity as! PersonProtocol).wrappedFirstName)")

【讨论】:

我测试了它,我摆脱了?,它的工作原理:) 太棒了!这 ?当然取决于变量是否在 CoreData/Object 类中是可选的。

以上是关于使用 Core Data 在 SwiftUI ForEach 中为 Data.Element 键入未知数的主要内容,如果未能解决你的问题,请参考以下文章

使用 Core Data 在 SwiftUI ForEach 中为 Data.Element 键入未知数

SWIFTUI Core Data 传递数字

在 SwiftUI 中将 @FetchRequest 与 Core Data 一起使用时修改 nil 排序行为

使用 Core Data 提供的数据(在 SwiftUI 中)并与另一个视图共享

Swift之深入解析如何结合Core Data和SwiftUI

如何从存储在 Core Data SwiftUI 中的数据计算平均值