【发布时间】:2018-01-26 17:12:30
【问题描述】:
我想要做的是重新排序我的 tableview 单元格。我的 tableview 有几个部分:数据模型很简单:产品列表,每个产品都有一个类别。
我正在使用 UITableViewDropDelegate,UITableViewDragDelegate 因为我不喜欢 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
}
更新
记录数Ofrowinsection:
我只有三个部分,每个部分只有一个项目
section : 2
sections[section].numberOfObjects: 1
section : 0
sections[section].numberOfObjects: 1
section : 1
sections[section].numberOfObjects: 1
section : 2
sections[section].numberOfObjects: 1
section : 0
sections[section].numberOfObjects: 1
section : 1
sections[section].numberOfObjects: 1
section : 2
sections[section].numberOfObjects: 1
section : 0
sections[section].numberOfObjects: 1
section : 1
sections[section].numberOfObjects: 1
section : 2
sections[section].numberOfObjects: 1
section : 0
sections[section].numberOfObjects: 1
section : 1
sections[section].numberOfObjects: 1
当我从第二部分的项目拖放到第一部分时
section
section : 0
sections[section].numberOfObjects: 1
section : 1
sections[section].numberOfObjects: 1
section : 2
sections[section].numberOfObjects: 1
018-01-26 19:56:05.492956+0100 ShopTogether[8815:1168659] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3698.33.6/UITableView.m:2011
2018-01-26 19:56:05.513608+0100 ShopTogether[8815:1168659] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (1 moved in, 0 moved out).'
// 更新 Fetchcontroller
我认为问题出在我显示这些部分时
事实上,当我将 nil 放入 sectionNameKeyPath: nil ==> 时,我的表格视图不再有任何部分,我也没有崩溃了但我想要表格视图中的部分。
fetchedResultsController =
NSFetchedResultsController(fetchRequest: Myrequest, managedObjectContext: Mycontext,
sectionNameKeyPath: nil, cacheName: nil)
我仍在寻找答案,但我希望tableview中允许在不同部分之间拖放。
【问题讨论】:
-
您确定是
let MyDestSection = objects[destinationIndexPath.row]而不是let MyDestSection = objects[destinationIndexPath.section]?并且请遵守变量和函数名称以小写字母开头并且是camelCased而不是snake_cased的命名约定 -
@vadian :我更新代码符合命名约定。我尝试了你的建议,仍然有同样的错误。
-
将
objects[destinationIndexPath.row]更改为objects[destinationIndexPath.section]是否可以解决问题? -
@vadian 没有同样的错误。
-
如果您移动或删除行,您的对象模型需要与您所做的表更改一致。即来自“numberOfRowsInSection”委托的结果。我看不到您是如何将对象分成多个部分的,请查看“numberOfRowsInSection”或“cellForRowAt:”以获得您的答案。
标签: ios uitableview core-data nsfetchedresultscontroller swift4