SWIFT 4:使用fetchedResultsController重新排序TableView

时间:2018-01-26 17:12:31

标签: ios uitableview core-data nsfetchedresultscontroller swift4

好吧,我一直在努力(3周),我找不到任何解决方案。

我要做的是重新排序我的tableview单元格。 我的tableview有部分:数据模型简单:产品列表和每个产品都有一个类别。

我正在使用UITableViewDropDelegate,UITableViewDragDelegate cz我不喜欢tableview中的编辑模式(红色按钮让我抓狂)

   func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {


    var objects = self.fetchedResultsController.fetchedObjects! as [TblProduits]
    self.fetchedResultsController.delegate = nil

    //get the destination section
    let myDestSection = objects[destinationIndexPath.row]

    let object = objects[sourceIndexPath.row]
    objects.remove(at: sourceIndexPath.row)

    //updating product categorie with the destination categorie before inserting 
    object.categorie = myDestSection.categorie

    objects.insert(object, at: destinationIndexPath.row)


    fctSaveListDesProduits()
    self.fetchedResultsController.delegate = self
  } 

当我尝试使用此错误将产品放入另一个部分时,我的应用程序崩溃了这个函数: 由于未捕获的异常'NSInternalInconsistencyException',原因:'无效更新:第0节中的行数无效。更新后的现有部分中包含的行数(5)必须等于该部分中包含的行数更新(5),加上或减去从该部分插入或删除的行数(0插入,0删除)和加或减移入或移出该部分的行数(1移入,0移出) 。“

任何人都可以帮助我。

/更新完整代码

 @IBOutlet var TblView_Produit: UITableView!

let Mycontext =  (UIApplication.shared.delegate   as! AppDelegate).persistentContainer.viewContext
let Myrequest : NSFetchRequest<TblProduits> = TblProduits.fetchRequest()
var fetchedResultsController : NSFetchedResultsController<TblProduits>!
var managedObjectContext: NSManagedObjectContext? = nil

override func viewDidLoad() {
    super.viewDidLoad()

     TblView_Produit.dragDelegate = self
    TblView_Produit.dropDelegate = self
   TblView_Produit.dragInteractionEnabled = true

    // Load Data
    Fct_loadListDesProduits()
    fetchedResultsController.delegate = self

}

func Fct_SaveListDesProduits() {
    do {
        try Mycontext.save()
        //    print ("saved ligne \(i)")
    } catch {
        debugPrint ("there is an error  \(error.localizedDescription)")
    }
}

  func Fct_loadListDesProduits () {



    let MySortDescriptor = NSSortDescriptor(key: #keyPath(TblProduits.categorie.categorie_Name), ascending: true)
    Myrequest.sortDescriptors = [MySortDescriptor]
    fetchedResultsController = NSFetchedResultsController(fetchRequest: Myrequest, managedObjectContext: Mycontext, sectionNameKeyPath:  #keyPath(TblProduits.categorie.categorie_Name), cacheName: nil)

    do {
        try  fetchedResultsController.performFetch()

    } catch {
        debugPrint ("there is an error  \(error.localizedDescription)")

    }
}


   func numberOfSections(in tableView: UITableView) -> Int {
    guard let sections = self.fetchedResultsController.sections else {
        return 0
    }

    return sections.count
}

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    guard let sections = self.fetchedResultsController.sections else {
        return 0
    }

    return sections[section].numberOfObjects
}

  func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    guard let sections = self.fetchedResultsController.sections else {
        return ""
    }

    return sections[section].name
}


// MARK: - FetchedResultsController Delegate

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {

    switch(type) {
    case .insert:
        if  let Myindexpath = newIndexPath {

            self.TblView_Produit.insertRows(at: [Myindexpath], with: .left)

        }
        break;

    case .delete:
        if let MyindexPath = indexPath {
            TblView_Produit.deleteRows(at: [MyindexPath], with: .fade)
        }
        break;

    case .move:


        break;
    case .update:


        break;
    }



}


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

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    TblView_Produit.beginUpdates()
}



func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ProduitTableViewCell
    if let ProduitName = self.fetchedResultsController.object(at: indexPath).produit_name { //ProductTable[indexPath.row].produit_name{


        cell.SetListeDesProduits(ProduitName: ProduitName)
    }
    //    cell.isEditing =  self.tableView(tableView, canMoveRowAt: indexPath)
    return cell
}


     func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {


var objects = self.fetchedResultsController.fetchedObjects! as [TblProduits]
self.fetchedResultsController.delegate = nil

//get the destination section
let myDestSection = objects[destinationIndexPath.section]

let object = objects[sourceIndexPath.row]
objects.remove(at: sourceIndexPath.row)

//updating product categorie with the destination categorie before inserting 
object.categorie = myDestSection.categorie

objects.insert(object, at: destinationIndexPath.row)


fctSaveListDesProduits()
self.fetchedResultsController.delegate = self
  } 

/ 更新:记录numberOfrowinsection **

我只有三个部分,每个部分只有一个项目

部分:2 sections [section] .numberOfObjects:1 部分:0 sections [section] .numberOfObjects:1 部分:1 sections [section] .numberOfObjects:1 部分:2 sections [section] .numberOfObjects:1 部分:0 sections [section] .numberOfObjects:1 部分:1 sections [section] .numberOfObjects:1 部分:2 sections [section] .numberOfObjects:1 部分:0 sections [section] .numberOfObjects:1 部分:1 sections [section] .numberOfObjects:1 部分:2 sections [section] .numberOfObjects:1 部分:0 sections [section] .numberOfObjects:1 部分:1 sections [section] .numberOfObjects:1

当我从第二部分到第一部分的项目拖放时 部分:0 sections [section] .numberOfObjects:1 部分:1 sections [section] .numberOfObjects:1 部分:2 sections [section] .numberOfObjects:1

018-01-26 19:56:05.492956 + 0100 ShopTogether [8815:1168659] *断言失败 - [UITableView _endCellAnimationsWithContext:],/ BuildRoot / Library / Cache / com.apple.xbs / Sources / UIKit_Sim / UIKit的-3698.33.6 / UITableView.m:2011 2018-01-26 19:56:05.513608 + 0100 ShopTogether [8815:1168659] * 由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第0部分中的行数无效。更新(1)后现有部分中包含的行必须等于更新(1)之前该部分中包含的行数,加上或减去从该部分插入或删除的行数(0已插入,0已删除) )加上或减去移入或移出该部分的行数(1移入,0移出)。'

//更新Fetchcontroller

我认为pb是我显示各节

的时候

实际上当我在sectionNameKeyPath中输入nil时:nil ==&gt;我的表视图已经没有任何部分了,我没有现金了但是我想在表格视图中找到部分

 fetchedResultsController = 
   NSFetchedResultsController(fetchRequest: Myrequest, managedObjectContext: Mycontext,
   sectionNameKeyPath: nil, cacheName: nil)

仍在搜索...,但我希望在tableview中允许在不同的部分之间拖放

1 个答案:

答案 0 :(得分:0)

我不确定这是最干净的方式但是我解决了我的pb:  更新类别后重新生成TableView并插入对象。

  func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {

    self.fetchedResultsController.delegate = nil
    var objects = self.fetchedResultsController.fetchedObjects
    let objectSource = fetchedResultsController.object(at: IndexPath(row: sourceIndexPath.row, section: sourceIndexPath.section))
    let MyCategorie = fetchedResultsController.object(at: IndexPath(row: 0, section: destinationIndexPath.section)).categorie
    objectSource.categorie = MyCategorie
    objects?.remove(at: sourceIndexPath.row)
    objects?.insert(objectSource, at: destinationIndexPath.row)
    Fct_SaveListDesProduits()
    self.fetchedResultsController.delegate = self
    // REGENRATING TABLEVIEW 
    Fct_loadListDesProduits()
 }