如何在 swift 中使用 fetchedresultscontroller 对 tableview 行重新排序?
How do I reorder tableview rows using fetchedresultscontroller in swift?
我正在尝试使用核心数据和 nsfetchresultscontroller 对 table 视图中的单元格进行重新排序。我找到了一些使用 objective C(对此我一无所知)的方法,并尝试在 swift 中实现它们,这是我想出的:
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
}
委托和上下文引用位于另一个文件的扩展名中。
使用此代码有时它可以工作,有时则不能。我更改了顺序,再次 运行 应用程序,它的顺序完全不同,我无法弄清楚。特别是当我一次移动不止一排时。如果我将每个对象的 "position" 属性打印到控制台,我可以看到它们确实没有正确更新。但为什么不呢?
我做错了什么?什么是更好的选择?
提前致谢,
丹尼尔
编辑:
好的,这是工作代码:
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 之前(很明显,但很容易错过)。
您需要使用 sortDescriptor,那么您从获取请求中获取的信息已经排序。这就是我实现 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
}()
您不应该编辑 books
,它不属于您,实际上是私人数据。相反,您应该只更新正在移动的对象以更改 position
值。如果您按照当前逻辑使用数组重新排序来执行此操作,则应创建 FRC 提供的数组的新可变副本。您还应该将位置的新值设置为 NSNumber
个实例。
我正在尝试使用核心数据和 nsfetchresultscontroller 对 table 视图中的单元格进行重新排序。我找到了一些使用 objective C(对此我一无所知)的方法,并尝试在 swift 中实现它们,这是我想出的:
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
}
委托和上下文引用位于另一个文件的扩展名中。 使用此代码有时它可以工作,有时则不能。我更改了顺序,再次 运行 应用程序,它的顺序完全不同,我无法弄清楚。特别是当我一次移动不止一排时。如果我将每个对象的 "position" 属性打印到控制台,我可以看到它们确实没有正确更新。但为什么不呢?
我做错了什么?什么是更好的选择?
提前致谢,
丹尼尔
编辑:
好的,这是工作代码:
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 之前(很明显,但很容易错过)。
您需要使用 sortDescriptor,那么您从获取请求中获取的信息已经排序。这就是我实现 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
}()
您不应该编辑 books
,它不属于您,实际上是私人数据。相反,您应该只更新正在移动的对象以更改 position
值。如果您按照当前逻辑使用数组重新排序来执行此操作,则应创建 FRC 提供的数组的新可变副本。您还应该将位置的新值设置为 NSNumber
个实例。