删除 tableView 中的错误行

Posted

技术标签:

【中文标题】删除 tableView 中的错误行【英文标题】:Deleting the wrong row in a tableView 【发布时间】:2018-03-11 00:49:24 【问题描述】:

我是 Swift 的初学者,并尝试构建一个应用程序,其中一个数组通过 Core Data 将项目保存在 tableView 中。这样可行。但是不能通过滑动删除正确的行。

首先删除右行。但是当我回到应用程序时,它是初始选定行上方的行已删除/不再显示。

哪位大神可以给点建议?

代码如下:

import UIKit
import CoreData

var shoppingList: [NSManagedObject] = [ ]

class ShoppingList_1: UIViewController, UITableViewDelegate, UITableViewDataSource 
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool 
        return true
    

    func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return shoppingList.count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let item = shoppingList[indexPath.row]
        let cell = Cell.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel?.text = item.value(forKeyPath: "itemName") as? String

        cell.detailTextLabel?.text = "\(indexPath.row)"
        return cell
    

    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) 
        let itemTmp = shoppingList[sourceIndexPath.row]
        shoppingList.remove(at: sourceIndexPath.row)
        shoppingList.insert(itemTmp, at: destinationIndexPath.row)
    

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) 
        if editingStyle == .delete
        
            shoppingList.remove(at: indexPath.row)
            Cell.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
             //Cell.reloadData()

            guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else return
            let managedContext = appDelegate.persistentContainer.viewContext
            managedContext.delete(shoppingList[indexPath.row])

            do 
                try managedContext.save()
               catch let err as NSError 
                print("12345", err)
            
        
    

    @IBOutlet weak var AddButton: UIButton!
    @IBOutlet weak var AddItem: UITextField!
    @IBOutlet weak var Cell: UITableView!

    override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(animated)
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else return
        let managedContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Item")
        do 
            shoppingList = try managedContext.fetch(fetchRequest)
         catch let err as NSError 
            print("Failed to fetch items", err)
        
    

【问题讨论】:

【参考方案1】:

您的问题是您将错误的对象传递给managedContext.delete,因为您在从数组中删除项目后按索引访问元素。事实上,如果你试图删除最后一行,你的应用就会崩溃。

如果您成功地从 Core Data 中删除了值,您也应该只更新您的本地数据模型和表。

你应该更新你的commit editingStyle方法如下:

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) 
    if editingStyle == .delete
    
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else return

        let managedContext = appDelegate.persistentContainer.viewContext
        managedContext.delete(shoppingList[indexPath.row])

        do 
            try managedContext.save()

            shoppingList.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
         catch let err as NSError 
            print("12345", err)
        
    

【讨论】:

哇!感谢您的快速帮助。现在它起作用了。现在我也可以删除最后一项了 :) 谢谢!【参考方案2】:

这是因为您首先从数组中删除元素,然后删除单元格,最后保存数组。我建议首先删除元素,然后保存数组,最后从 tableView 中删除单元格。为了确保您的应用程序始终遵循此顺序,请创建一个带有闭包的 delete() 函数。所有的数据库删除都应该在实际函数中完成,并且 tableViewCell 必须在闭包中删除,这样您就可以确定在其他所有操作都正确完成后它会被删除。

这是函数:

func deleteRows(closure: () -> ()) 
    shoppingList.remove(at: indexPath.row)
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else return
    let managedContext = appDelegate.persistentContainer.viewContext
    managedContext.delete(shoppingList[indexPath.row])

    do 
        try managedContext.save()

       catch let err as NSError 
        print("12345", err)
        return
    
    closure()

这就是你所说的:

deleteRows 
    tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)

【讨论】:

Maddy 的评论很有帮助。无论如何,感谢您的快速反应。我将看看“闭包”,并尝试弄清楚这意味着什么:)

以上是关于删除 tableView 中的错误行的主要内容,如果未能解决你的问题,请参考以下文章

使用 SearchBar 时,复选标记与 TableView 中的错误行相关联

Swift:tableView 行的高度,其 tableView 单元格具有动态行数的嵌套 tableView

删除行:错误“无效更新:第 0 节中的行数无效”

从 tableview 中删除一行

如何从 modalVC 中删除 VC 1 中的 tableView 行?

从 MoreNavigationController 中删除 tableView 中的多余行