【问题标题】:Fail on UITableView updateUITableView 更新失败
【发布时间】:2018-05-07 04:55:09
【问题描述】:

需要你们的帮助! 我只对 iOS 9 上的一个错误感到生气。 正如您在下面看到的,它在 iOS 11 上运行良好

一开始,我有 4 个单元格,新单元格的状态为“Nouveau”。 当我点击“新”单元格时,状态变为“En attente”(表示“等待”)。

在 iOS 9 上,一切都很好,直到最后一个单元格。当我点击最后一个“新”单元格时,它不会移动到“等待”并且“新”部分仍然存在。在此之后,表格视图不再更新,当我更改为另一个 viewController 并返回包含表格视图的那个时,它会恢复正常。

我正在使用 NSFetchedResultsController。数据不错,节数不错,按节划分的元素数量不错,标题也不错。

开头 1 部分标题为“Nouveau”,包含 4 个对象 最后,标题为“En attente”的 1 个部分包含 4 个对象

extension CRDashboardOrdersViewController: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        print( self.fetchResult?.sections?.count ?? 0 )
        return self.fetchResult?.sections?.count ?? 0
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        print( self.fetchResult?.sections?.get(index: section)?.numberOfObjects ?? 0 )
        return self.fetchResult?.sections?.get(index: section)?.numberOfObjects ?? 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: CRDashboardOrderTableViewCell = tableView.dequeueReusableCell(withIdentifier: "CRDashboardOrderTableViewCell") as! CRDashboardOrderTableViewCell
        let order: Order = self.fetchResult.object(at: indexPath) as! Order

        cell.order = order

        if let selectedIndexPath = self.selectedIndexPath, selectedIndexPath == indexPath {
            self.tableView.selectRow(at: selectedIndexPath, animated: false, scrollPosition: .none)
        }

        return cell
    }
}

extension CRDashboardOrdersViewController: UITableViewDelegate {
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            self.selectedIndexPath = indexPath
        }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        print( self.fetchResult?.sections?.get(index: section)?.name ?? "???" )
        return self.fetchResult?.sections?.get(index: section)?.name ?? "???"
    }
}

extension CRDashboardOrdersViewController: NSFetchedResultsControllerDelegate {
        func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
            self.tableView.beginUpdates()
        }

 func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
        print(sectionIndex)
        print(sectionInfo.indexTitle)
        switch type {
        case .insert:
            self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
        case .delete:
            self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
        default:
            break
        }
    }

  func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch type {
        case .update:
            self.tableView.reloadRows(at: [indexPath!], with: .fade)
            if indexPath == self.selectedIndexPath {
                self.selectedIndexPath = indexPath
            }
            break
        case .insert:
            self.tableView.insertRows(at: [newIndexPath!], with: .fade)
            self.selectedIndexPath = nil
            break
        case .delete:
            self.tableView.deleteRows(at: [indexPath!], with: .fade)
            self.selectedIndexPath = nil
            break
        case .move:
            self.tableView.moveRow(at: indexPath!, to: newIndexPath!)
            if indexPath == self.selectedIndexPath {
                self.selectedIndexPath = newIndexPath
            }
            break
        }
    }

 func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        self.tableView.endUpdates()
    }
}

【问题讨论】:

    标签: ios swift uitableview ipad nsfetchedresultscontroller


    【解决方案1】:

    您的 cellForRow: 和 FetchedResults 委托有误。

    当使用 FetchedResultsController 时,在 .update 上你不应该使用 reloadRows,这会导致问题,相反你应该有一个像这样更新单元模型的方法:

    func updateCell(atPath indexPath: IndexPath) {
        if let cell = tableView.cellForRow(at: indexPath) as? MyCell {
            updateCell(withCell: cell, atIndexPath: indexPath)
        }
    }
    
    func updateCell(withCell cell: MyCell, atIndexPath indexPath: IndexPath) {
        if let MyModel = fetchedResultsController?.object(at: indexPath) {
            cell.model = myModel
    }
    }
    

    然后在您的委托 .update 中调用 updateCell(AtIndexPath) 来更新单元格 UI。

    您还应该在 cellForRow 中使用此单元格配置方法

    【讨论】:

    • 感谢您的回复 遗憾的是,它并没有解决问题:/
    • 但是在调用 moveRow 时,我只看到当前 indexPath 是 (0,0) 而 newIndexPath 是 (0,1),这对的第一个值似乎是部分,第二个似乎成为行。但看起来第 0 节目前没有被删除。感觉应该首先将单元格移动到 indexPath(1,x) 然后删除第 0 节。我只是测试并在 moveRow 之前调用 deleteSection
    • 不要使用移动,而是尝试删除 indexPath 并插入 newIndexPath,这将在 newIndexpAth 上调用 .update
    • 爱你!救了我的命 !有点奇怪,但它正在工作!
    猜你喜欢
    • 1970-01-01
    • 2012-12-23
    • 2022-01-17
    • 2014-03-01
    • 2015-09-24
    • 2015-05-20
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多