CoreData fetch() 返回无序对象

Posted

技术标签:

【中文标题】CoreData fetch() 返回无序对象【英文标题】:CoreData fetch() returns objects unordered 【发布时间】:2018-06-07 19:10:45 【问题描述】:

我有一个实体,它有一个名称,出于测试目的,我按照最近添加 (0) 到最旧添加的对象的顺序命名它们。

当我第一次启动应用程序时,它会按顺序加载我的实体(0,1,2...),但是如果我更改任何实体的名称属性,那么顺序就会一团糟。我使用 numberOfRows tableview 函数来测试这个,当重新加载 tableView 时调用它(如果我错了,请纠正我):

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else return 0
    let managedContext = appDelegate.managedObjectContext
    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "GraphDataSet")
    do 
        graphSetArray.removeAll()
        graphSetArray = try managedContext.fetch(fetchRequest)
     catch let error as NSError 
        print("Could not fetch. \(error), \(error.userInfo)")
    
    for i in 0..<graphSetArray.count
        let set = graphSetArray[(graphSetArray.count-1)-i]
        print("Name: ", set.value(forKeyPath: "name") as? String)
    
    return graphSetArray.count

据我所知,这会清空包含所有实体的数组(尽管我认为这是没有意义的,因为它被设置在下一行,但我想确定一下),然后获取填充数组的实体。然后我向后循环遍历数组(从最近到旧)并获取该索引的实体并打印其名称属性。

这是我每次启动应用程序时的控制台输出:

Name:  Optional("0")
Name:  Optional("1")
Name:  Optional("2")
Name:  Optional("3")
Name:  Optional("4")
Name:  Optional("5")
Name:  Optional("6")

这是在我将实体名称值更改为与原来相同的值之后(只是为了保持它的顺序,但在技术上更改值并重新加载 tableView):

Name:  Optional("5")
Name:  Optional("4")
Name:  Optional("1")
Name:  Optional("3")
Name:  Optional("0")
Name:  Optional("2")
Name:  Optional("6")

不知道为什么会发生这种情况,因为我每次都以相同的方式获取数据,并且每次重新启动应用程序时,订单都会恢复正常。我唯一的理论是,当实体属性发生变化时,排序就会混乱,没有模式。所以我想知道这个理论是否正确,如果是,那么有什么办法可以阻止顺序改变?

编辑:我刚刚注意到的一件事是,在它出现故障后,每次当我更改值时,它都会保持这个未排序的顺序

【问题讨论】:

【参考方案1】:

顺序不一定保留在 CoreData 中,但您可以将排序描述符添加到您的 fetch 请求中,以便以某种方式对其进行排序。如果您希望它按添加的时间排序,则需要在模型中添加时间戳并按此排序。

let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "GraphDataSet")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
...

【讨论】:

好的,但是有什么理由让它按顺序加载一次,然后每次加载相同的未排序顺序。每次重新启动应用程序时,未排序的顺序都是不同的,但在应用程序的执行中是一致的 它可能保存在 ram 中,因此之后不会更改顺序,但我不能肯定地告诉你。我可以告诉你的是,订单不能保证保持不变。 好的,我正在实现一个时间戳,我只是为此使用一个属性?【参考方案2】:

您确定使用数组作为后备存储吗?自动生成的版本实际上可以是 Sets 而不是 Arrays。

您的提取请求还可以应用排序描述符,以确保结果(无论它们如何存储)以您指定的方式显示给您。

【讨论】:

我没有看到任何方法来指定它作为一个数组获取,但我相信它是一个集合,无法像我在发布的代码中那样使用下标来索引。我读了一个解决方案,有人建议将索引保存为实体的属性,然后使用排序顺序,这是正确的做法吗?同样使用该方法删除实体的最佳解决方案是什么? 抱歉,出于某种原因,我认为您的 GraphDataSet 是从关系中获取的。听起来您实际上应该使用排序描述符 - 并且不要在表视图委托方法中每次都获取这样的数据。理想情况下,您应该查看 Ray Wenderlich 或 objc.io 的 CoreData 书籍 我要实现排序描述符。除了委托中的每次之外,还有另一种获取方式吗?如果一个值被添加/删除,它不需要检查整个数组吗? 谢谢你的帮助,我去看看书 如果你正在使用 UITableViews,你应该考虑使用 NSFetchedResultsController。正确连接后,您不必担心更新表格视图,因为在您更改数据后它都会为您刷新。

以上是关于CoreData fetch() 返回无序对象的主要内容,如果未能解决你的问题,请参考以下文章

从 fetch 请求返回的对象包含不正确的数据

CoreData - fetch 找不到对象

核心数据 - 访问从 fetch EXC_BAD_ACCESS 返回的对象

不相关实体的CoreData Fetch Predicate

核心数据 - 获取对象数组的最后一个对象?

CoreData Fetch (Sort by Date) - 不更新新数据?