【问题标题】:How do I reorder tableview rows using fetchedresultscontroller in swift?如何在 swift 中使用 fetchedresultscontroller 重新排序 tableview 行?
【发布时间】: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 之前(很明显,但很容易错过)。

【问题讨论】:

    标签: ios swift uitableview core-data nsfetchedresultscontroller


    【解决方案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。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 2013-04-18
    相关资源
    最近更新 更多