如何在swift中使用fetchedresultscontroller重新排序tableview行?

时间:2015-10-07 09:21:20

标签: ios swift uitableview core-data nsfetchedresultscontroller

我正在尝试使用核心数据和nsfetchresultscontroller重新排序表视图中的单元格。我找到了一些方法,使用目标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

}

委托和上下文引用位于另一个文件的扩展名中。 使用此代码有时它可以工作,有时它不会。我改变了顺序,再次运行应用程序,这是一个完全不同的顺序,我无法弄清楚。特别是当我一次移动多行时。如果我将每个对象的“位置”属性打印到控制台,我可以看到它们确实没有正确更新。但为什么不呢?

我做错了什么?什么是更好的选择?

提前致谢,

丹尼尔

编辑:

好的,这是工作代码:

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之前(显然,但很容易错过)。

2 个答案:

答案 0 :(得分:4)

您不应该编辑books,它不属于您,并且实际上是私人数据。相反,您应该只更新正在移动的对象以更改position值。如果使用当前逻辑中的数组重新排序来执行此操作,则应创建FRC提供的阵列的新可变副本。您还应该将位置的新值设置为NSNumber个实例。

答案 1 :(得分:0)

您需要使用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
}()