简体   繁体   English

在tableView中删除错误的行

[英]Deleting the wrong row in a tableView

I'm a beginner in Swift and tried to build an app where an array saves the items in a tableView by Core Data. 我是Swift的初学者,并尝试构建一个应用程序,其中数组将项通过Core Data保存在tableView中。 That works. 这样可行。 But what won't work is to delete the right row by swiping. 但是,行不通的方法是通过滑动删除右侧的行。

It is deleted the right row first. 它首先被删除在右行。 But when I go back to the app, it is the row above the initial selected row deleted/not shown anymore. 但是,当我返回到应用程序时,它是最初选定行上方的行已删除/不再显示。

Anybody there who could give an advice? 有人可以提供建议吗?

Here is the code: 这是代码:

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)
        }
    }
}

Your issue is you are passing the wrong object to managedContext.delete because you access the element by index after you remove the item from the array. 您的问题是您将错误的对象传递给managedContext.delete因为在从数组中删除该项之后,您通过索引访问了元素。 In fact, if you tried to delete the last row your app would crash. 实际上,如果您尝试删除最后一行,您的应用将崩溃。

You should also only update your local data model and the table if you successfully remove the value from Core Data. 如果您已成功从Core Data中删除了该值,则还应该仅更新本地数据模型和表。

You should update your commit editingStyle method as follows: 您应该按照以下方式更新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)
        }
    }
}

This happens because you first delete the element from the array, then remove the cell and then finally save the array. 发生这种情况是因为您首先从数组中删除了元素,然后删除了单元格,然后最后保存了数组。 I would suggest firstly deleting the element, then saving the array and finally removing the cell from the tableView. 我建议先删除元素,然后保存数组,最后从tableView中删除单元格。 In order to ensure that your application always follows this order, create a delete() function with a closure. 为了确保您的应用程序始终遵循此顺序,请创建一个带闭包的delete()函数。 All the database removal should be done in the actual function, and the tableViewCell must be removed in the closure, so that you are sure that it gets removed after everything else is correctly done. 所有数据库删除都应在实际函数中完成,并且tableViewCell必须在闭包中删除,以便确保在正确完成所有其他操作后将其删除。

This is the function: 这是功能:

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()
}

This is you calling it: 这就是你所说的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM