删除行后UITableView不会更新

时间:2016-11-23 11:44:27

标签: ios swift uitableview swift3

我在swift 3.0中处理一个项目,我有两个UITableViews,我在其中设置从名为UserIncome的核心数据模块实体获取的数据。由于这些数据将在单个UIViewController中的两个UItableView中填充(基于ViewWillAppear委托方法中的String值进行过滤),一旦在一个UITableView中删除了一行,其数组也会自动由其他tableView的对象更新。但是,一旦我单击后退按钮并回到相同的UIViewController,一切似乎都很好。我的要求是在删除行后更新UItableView以作为核心数据模块。代码如下。我在这里缺少什么?

 import UIKit
import CoreData

class MyIncomesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var recurringIncomeTableView: UITableView!
    @IBOutlet weak var otherIncomeTableView: UITableView!
    //var myIncomeType : String?

    var stores = [UserIncome] ()
    var other = [UserIncome] ()
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    var rowTbl : Int!
    var rowTbl2 : Int!



    override func viewDidLoad() {
        super.viewDidLoad()

}
    override func viewDidAppear(_ animated: Bool) {

        stores.removeAll()
        other.removeAll()

        let request = NSFetchRequest <NSFetchRequestResult> (entityName: "UserIncome")
        request.returnsObjectsAsFaults = false



        do {

            let results = try context.fetch(request) as! [UserIncome]

            print("Results from the fetch request are : ", request)

            // check data existance
            if results.count>0 {
                print("results are :", results.count)

                for resultGot in results {

                    //lets check if the data is available and whether the loop is working by printing out the "name"
                    if let incName = resultGot.incomeName {
                        print("expence name is :", incName)

                        //set the value to the global variable as to filter the arrays 
                        let myIncomeType = resultGot.incomeType

                        if myIncomeType == "Recurring Income"{

                          stores += [resultGot]
                          print("my recurring income array is : \(stores)")
                        }else if myIncomeType == "Other Income"{

                          other += [resultGot]
                          print("my other income array is : \(other)")
                        }
                    }
                }
                self.recurringIncomeTableView.reloadData()
                self.otherIncomeTableView.reloadData()

            }

        }catch{


            print("No Data to load")
        }


    }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if tableView.tag == 1 {
        let cell: RecuringIncomeTableViewCell = tableView.dequeueReusableCell(withIdentifier: "recurringIncomeCell") as! RecuringIncomeTableViewCell

        let store = stores [indexPath.row]

        cell.incomeNameLabel.text = store.incomeName
        cell.amountLabel.text = store.amount


        return cell

        }
        else {
            let cell: OtherIncomeTableViewCell = tableView.dequeueReusableCell(withIdentifier: "otherIncomeCell") as! OtherIncomeTableViewCell

            let otherIncomes = other [indexPath.row]

            cell.incomeNameLabel.text = otherIncomes.incomeName
            cell.amountLabel.text = otherIncomes.amount


            return cell

        }
    }




    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        //performSegue(withIdentifier: "editStore", sender: nil)
        if tableView.tag == 1 {
           rowTbl = tableView.indexPathForSelectedRow?.row
            print("current row in tbl 1 is : ",rowTbl)

        }else {

          rowTbl2 = tableView.indexPathForSelectedRow?.row
            print("current row in tbl 2 is : ",rowTbl2)
        }

    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "editRecurringIncome"{

            let v = segue.destination as! AddIncomeViewController
            let indexPath = self.recurringIncomeTableView.indexPathForSelectedRow
            let row = indexPath?.row
            v.store = stores[row!]

        }else if segue.identifier == "editOtherIncome" {
            let t = segue.destination as! AddIncomeViewController
            let indexPath = self.otherIncomeTableView.indexPathForSelectedRow
            let row = indexPath?.row
            t.store = other [row!]

        }
    }

//    

    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        print("delete delegate being activated")
        return true
    }

    //For remove row from tableview & object from array.
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        if tableView.tag == 1 {
            if editingStyle == .delete {
                let task = stores [indexPath.row]
                context.delete(task)
                (UIApplication.shared.delegate as! AppDelegate).saveContext()


                do {
                    stores = try context.fetch(UserIncome.fetchRequest())
                    print("Stores deleted from indexPath",stores)
                }catch{
                    print("fail")
                }


               recurringIncomeTableView.reloadData()

            }

            self.recurringIncomeTableView.reloadData()

        } else if tableView.tag == 2 {
            if editingStyle == .delete {
                let task = other[indexPath.row]
                print("task on otherTblView is : ",task)
                context.delete(task)
                (UIApplication.shared.delegate as! AppDelegate).saveContext()
                otherIncomeTableView.reloadData()

                do {
                    other = try context.fetch(UserIncome.fetchRequest())
                    print("Stores deleted from indexPath",other)
                }catch{
                    print("fail")
                }

        }


            self.otherIncomeTableView.reloadData()
        }
        tableView.reloadData()


    }


}

2 个答案:

答案 0 :(得分:1)

你需要像这样删除任务

let task = stores [indexPath.row]
context.delete(task)
stores.removeAtIndex(indexPath.row) // i think you forget this line
(UIApplication.shared.delegate as! AppDelegate).saveContext()

试试这个,希望它能帮到你

答案 1 :(得分:0)

核心数据对象实际上并不包含任何信息。它有一个指向上下文和ID的指针,所以当你向它询问信息时,它会去商店询问。如果从上下文中删除该对象,则您存储在数组中的管理对象将不再起作用并将崩溃。这就是你永远不应该保留NSManagedObjects的原因。

a)将核心数据中的值复制到另一个对象中。如果要删除对象,则必须从商店和要保留的副本中删除该对象。如果插入新对象,或者从viewController之外的某些其他源删除它们,它将不会更新(但也不会崩溃)。

b)使用NSFetchedResultsController并在值更改时更新结果。这将使代表在发生变化时告诉您。所以你要做的就是从商店中删除对象,然后fetchedResultsController将告诉你何时删除它。