SwiftUI 中的 CoreData:如何清楚地获取属性?
Posted
技术标签:
【中文标题】SwiftUI 中的 CoreData:如何清楚地获取属性?【英文标题】:CoreData in SwiftUI: How to fetch a property distinctly? 【发布时间】:2020-02-02 13:55:53 【问题描述】:我花了好几个小时来弄清楚如何从数据模型 (CoreData) 的属性中唯一地获取值。
例如,如果我有 3 条记录,它们的 WrappedName 属性中分别包含“Apple”、“Banana”和“Apple”,则 ListView 将显示“Apple”、“Banana”和“Apple”(3 行)。
但我只想显示“Apple”和“Banana”(2 行)。
我怎样才能做到这一点?
//ListView.swift
import SwiftUI
import CoreData
struct ListView: View
@FetchRequest(entity: Data.entity(), sortDescriptors: []) var data: FetchedResults<Data>
var body: some View
NavigationView
List
ForEach(data, id: \.self) d in
NavigationLink(destination: ChartView(title: d.wrappedName)
Text(d.wrappedName)
//Data+CoreDataProperties.swift
import Foundation
import CoreData
extension Data
@nonobjc public class func fetchRequest() -> NSFetchRequest<Data>
return NSFetchRequest<Data>(entityName: "Data")
@NSManaged public var date: Date?
@NSManaged public var id: UUID?
@NSManaged public var name: String?
public var wrappedName: String
name ?? "Unknown"
【问题讨论】:
帮助提示:将extension Data
更改为extension Data: Identifiable
,或者更好地添加单行extension NSManagedObject: Identifiable
以使所有NSManagedObject
s 符合Identifiable
协议,您可以更改其中的一行你的List
视图到ForEach(data) d in
。不是很大的改进,但更易于阅读。
【参考方案1】:
设置Published
var 的自定义Notification
会更好
public init()
self.uniqueDict = [NSDictionary]()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(setUniqueDictValue), name: NSNotification.Name.NSManagedObjectContextObjectsDidChange, object: managedObjectContext)
//set the uniqueDict variable
setUniqueDictValue()
private func getEntityFetchRequest() -> NSFetchRequest<NSDictionary>
let fetchRequest = NSFetchRequest<NSDictionary>(entityName: "YourModel")
let sortDescriptor = NSSortDescriptor(key: "name", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType
fetchRequest.propertiesToFetch = ["name"]
fetchRequest.returnsDistinctResults = true
return fetchRequest
///Single Fetch of objects willSet uniqueDict variable
func setUniqueDictValue()
do
try self.uniqueDict = managedObjectContext.fetch(getEntityFetchRequest())
catch
fatalError("Failed to fetch entity: \(error)")
不同的结果示例项目 https://www.youtube.com/watch?v=xl3KVmBJrSg
【讨论】:
@Ray 在我回答了这个问题后,我做了一个小示例项目并上传了一个视频。 youtube.com/watch?v=-U-4Zon6dbE 看完了你的教程!但是要使用fetchRequest.returnsDistinctResults = true
,它需要fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType
,但随后出现错误'NSFetchedResultsController 不支持NSDictionaryResultType 的更改跟踪和获取请求'。你能给我建议吗?
因为将其切换到字典意味着您不再获得对象数组,而是获得“wrappedName”/String 的字典。需要删除 'fetchController!.delegate = self' 行。每次您想要一个新列表时,您都必须触发 initFetchedResultsController() 方法。在 ViewModel ADD '@Published var uniqueDict: [NSDictionary]' 中,向 init() 添加 'self.uniqueDict = [NSDictionary]()',将所有 'YourModel' 更改为 'NSDictionary'。在 ListView 中更改 'List(viewModel.uniqueDict, id: \.self)obj in Text((obj as NSDictionary).allValues.first as!String)'
这是另一个示例项目youtube.com/watch?v=xl3KVmBJrSg
如果没有controllerDidChangeContent
,当从其他视图添加新数据时,ListView 不会更新......但这使得使用returnsDistinctResults
成为不可能......我想我需要采取不同的方法,直到@ 987654331@ 支持不同的结果。感谢您的详细说明!【参考方案2】:
您需要更改您的核心数据模型。该模型应该按照您希望在 UI 中显示的方式进行设计。不要把它设计成数据库。
在您的情况下,另一个实体名为 Fruit,其 int fruitType 是唯一键,Apple 为 1,Banana 为 2。在您的数据实体中有一个关系水果,但现在不是获取数据而是获取水果。如果您想在列表单元格中显示有关数据的内容,只需向 Fruit 类添加一个属性即可从相关数据中检索它。并且使用 KVO 观察,您可以使上下文在其相关 Data 中的某些内容发生更改时检测到 Fruit 的更改。
【讨论】:
以上是关于SwiftUI 中的 CoreData:如何清楚地获取属性?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 SwiftUI 中的颜色类型存储到 CoreData 中?
Swift之深入解析如何结合Core Data和SwiftUI
我如何(或应该?)用嵌套的 managedObjectContext 替换这个 CoreData SwiftUI 应用程序中的 MVVM?