【问题标题】:NSFetchedResultsController getting crash while displaying in TableviewNSFetchedResultsController 在 Tableview 中显示时崩溃
【发布时间】:2020-09-08 22:41:24
【问题描述】:

我收到如下服务器响应

[[“image_url": https://someurl1, "title": Title1], ["image_url": https://someurl2, "title": Title2], ["image_url": https://someurl3, "title": Title3], ["image_url": https://someurl4, "title": Title4]]

我将这些数据循环存储到核心数据中。

所以,我正在尝试使用 NSFetchedResultsController 从核心数据中获取这些数据,并尝试在 Tableview 中显示

    func saveDataToDataBase(json: [[String: Any]]) {
        for eachData in json {
            Categories.saveCategories(jsonResponse: eachData, completionHandler: { [weak self] success in
                if (success) {
                }
            })
        }

 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        self.fetchData()
            }            
        }


func fetchData() {
    fetchedResultsController = NSFetchedResultsController(fetchRequest: allCategoriesData(), managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
    fetchedResultsController?.delegate = self
     do {
        try fetcheResultsController()!.performFetch()
      } catch let error as NSError {
        print("Could not fetch. \(error), \(error.localizedDescription)")
     }

}

 func allCategoriesData() -> NSFetchRequest<NSFetchRequestResult> {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: HomeKeyConstant.Entity_Categories)
        let sortDescriptor = NSSortDescriptor(key: HomeKeyConstant.categories_Id, ascending: true)
        fetchRequest.predicate = nil
        fetchRequest.sortDescriptors = [sortDescriptor]
        return fetchRequest
    }

// UITableviewDelegate & Data Source methods

 func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        guard let sectionCount = fetchedResultsController.sections?.count else {
        return 0
       }
       return sectionCount
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if self.fetchedResultsController == nil {

        } else {
            if let sectionData = fetchedResultsController.sections?[section] {
                return sectionData.numberOfObjects
            }
        }

        return 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell  = homeTableView.dequeueReusableCell(withIdentifier: HomeKeyConstant.key_Cell_Identifier, for: indexPath) as! HomeTableViewCell
        self.configureCell(cell, at: indexPath)
        return cell
    }

    func configureCell(_ cell: HomeTableViewCell?, at indexPath: IndexPath?) {

        let category = fetchedResultsController.object(at: indexPath!) as! Categories
        cell?.tableTitleLabel.text = category.value(forKey: HomeKeyConstant.categories_Title) as? String
        cell?.tableDescriptionLabel.text = category.value(forKey: HomeKeyConstant.ctegories_Description) as? String

    }

// MARK: - FetchedResultsController Delegate
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    homeTableView.beginUpdates()
    }

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

    func controller(controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
    switch type {
    case .insert:
        homeTableView.insertSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .automatic)
    case .delete:
        homeTableView.deleteSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .automatic)
    default: break
    }
    }

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    switch type {
    case .insert:
        homeTableView.insertRows(at: [(newIndexPath! as IndexPath)], with: .automatic)
    case .delete:
        homeTableView.deleteRows(at: [(indexPath! as IndexPath)], with: .automatic)
    default: break
    }
    }

实际上,我存储了 4 个数据索引。在获取其显示为 50 个索引和崩溃时

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第0节中的行数无效。更新后现有节中包含的行数(50)必须等于行数更新前包含在该节中的行数 (0),加上或减去从该节插入或删除的行数(1 插入,0 删除),加上或减去移入或移出该节的行数(0 移入, 0 移出)。'

我有疑问,在我的表格视图中我没有编辑/删除/插入/更新选项。只是我必须从数据库中获取数据,并且必须在 tableview 中显示。

那么,这些 NSFetchedResultsControllerDelegate 方法是需要实现还是不需要呢? 如何修复此崩溃?

【问题讨论】:

  • 您的代码看起来不错。但我建议在您的 FRC 委托方法中处理 NSFetchedResultsChangeType.move。
  • 如果实现了委托方法,则不得重新获取数据。 NSFetchedResultsController 应该被创建一次作为惰性实例化属性。

标签: ios swift uitableview core-data nsfetchrequest


【解决方案1】:

我认为这里的问题是您将数据保存到数据库中。保存后,您无需等待他们完成并更新您的 TableviewController。所以如果你有一点数据要保存。此代码将正常工作,否则将崩溃。

【讨论】:

  • 我试过这个 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.fetchData() } // 但仍然没有加载数据,它只显示空 UI跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
相关资源
最近更新 更多