如何在 swift 中使用 fetchedresultscontroller 重新排序 tableview 行?
Posted
技术标签:
【中文标题】如何在 swift 中使用 fetchedresultscontroller 重新排序 tableview 行?【英文标题】:How do I reorder tableview rows using fetchedresultscontroller in swift? 【发布时间】:2015-10-07 09:21:20 【问题描述】:我正在尝试使用核心数据和 nsfetchresultscontroller 重新排序表格视图中的单元格。我发现了一些使用 Objective C 的方法(我对此一无所知)并尝试快速实现它们,这就是我想出的:
var books: Array<AnyObject> = []
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
books = fetchedResultsController.fetchedObjects!
let book = fetchedResultsController.objectAtIndexPath(fromIndexPath)
self.fetchedResultsController.delegate = nil
books.removeAtIndex(fromIndexPath.row)
books.insert(book, atIndex: toIndexPath.row)
var i = 0
for book in books
book.setValue(i++, forKey: "position")
try! context.save()
self.fetchedResultsController.delegate = self
委托和上下文引用在另一个文件的扩展中。 使用此代码有时可以工作,有时不能。我更改了顺序,再次运行应用程序,它的顺序完全不同,我无法弄清楚。尤其是当我一次移动不止一排时。如果我将每个对象的“位置”属性打印到控制台,我可以看到它们确实没有正确更新。但为什么不呢?
我做错了什么?什么是更好的选择?
提前致谢,
丹尼尔
编辑:
好的,下面是工作代码:
func initializeFetchedResultsController()
let request = NSFetchRequest(entityName: "Book")
let sortDescriptor = NSSortDescriptor(key: "position", ascending: true)
request.sortDescriptors = [sortDescriptor]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
self.fetchedResultsController.delegate = self
do
try self.fetchedResultsController.performFetch()
catch
fatalError("Failed to initialize FetchedResultsController: \(error)")
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
initializeFetchedResultsController()
var objects = self.fetchedResultsController.fetchedObjects! as! [ObjectClass]
self.fetchedResultsController.delegate = nil
let object = objects[fromIndexPath.row]
objects.removeAtIndex(fromIndexPath.row)
objects.insert(object, atIndex: toIndexPath.row)
var i = 0
for object in objects
object.position = i++
try! context.save()
self.fetchedResultsController.delegate = self
诀窍是 initializeFetchedResultsController 函数,除了在 viewDidLoad 中,我有它,必须在 moveRowAtIndexPath 位内重复。此外,初始化函数和数组声明都必须在将 FRC 委托设置为 nil 之前(很明显,但很容易错过)。
【问题讨论】:
【参考方案1】:你不应该编辑books
,它不属于你,实际上是私人数据。相反,您应该只更新正在移动的对象以更改 position
值。如果您按照当前逻辑使用数组重新排序来执行此操作,您应该创建 FRC 提供的数组的新可变副本。您还应该将位置的新值设置为 NSNumber
实例。
【讨论】:
嗯,我以为它已经是可变副本了。那我该怎么做呢?对不起,愚蠢的问题,这是我第一次尝试编程。 从文档中并不完全清楚,在 obj-c 中它是不可变的,在 swift 中它很可能是您可以编辑的副本。可能NSNumber
部分是问题所在。
那么,我应该只使用“i as NSNumber”吗?我试过了,xcode没有抱怨,但它仍然不起作用。 :(
我正在考虑如何更新正在移动的对象,就像你说的那样。问题是,当我删除和对象时,我必须将其后的每个对象的位置减少一个,而且我不知道如果没有数组该怎么做......
数组应该没问题,调试以检查循环期间将哪些数字更新到托管对象中【参考方案2】:
您需要使用 sortDescriptor,然后您从 fetch 请求返回的信息已经排序。这就是我实现 fetchRequests 的方式:
lazy var connectionsFetchRequest: NSFetchRequest =
var request = NSFetchRequest(entityName: "Connection")
let predicate = NSPredicate(format: "%K == %@", argumentArray: ["user", UserManager.SharedInstance.user!])
request.sortDescriptors = [NSSortDescriptor(key: "firstName", ascending: true)]
request.predicate = predicate
return request
()
【讨论】:
我正在这样做……我会用代码更新问题。 请显示更多代码。我们需要知道你已经在做什么。请发布您的 fetchRequest。以上是关于如何在 swift 中使用 fetchedresultscontroller 重新排序 tableview 行?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 kotlin native 中使用 swift 库?
如何在 Swift 中使用 Apple 地图 - 你必须使用 C 还是 Swift 可以?