使用Swift 3中的CoreData从表视图中删除对象

时间:2017-01-17 22:22:35

标签: ios swift core-data

我今天开始学习CoreData,我在Ray Wenderlich(https://www.raywenderlich.com/145809/getting-started-core-data-tutorial)上学习了很好的教程

完成的项目以表格视图结束,填充了用户通过导航栏中的“添加”按钮输入的标签。

我也继续使用删除功能,因为那不在教程中:

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
    if editingStyle == .delete
    {

        guard let appDelegate =
            UIApplication.shared.delegate as? AppDelegate else {
                return
        }

        tableView.beginUpdates()
        companies.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .fade)
        tableView.endUpdates()

        appDelegate.saveContext()
    }
}

然而,当我导航到另一个视图控制器然后返回时,已删除的对象再次出现。我将公司初始化为文件顶部的托管对象:

var companies = [NSManagedObject]()

我想

companies.remove(at: indexPath.row)

接着是

appDelegate.saveContext()
删除函数中的

会从数据源中删除该对象,但就像我说它仍然在那里。

如何删除对象,以便当我离开页面并返回时,它仍然被删除,但如果我重新启动应用程序,它会回来?

编辑(适用于我的代码)

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{

    let company = companies[indexPath.row]

    if editingStyle == .delete {
        managedContext.delete(company)

        do {
            try managedContext.save()
        } catch let error as NSError {
            print("Error While Deleting Note: \(error.userInfo)")
        }

    }

    // Fetch new data/reload table
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: companyEntity)

    do {
        companies = try managedContext.fetch(fetchRequest) as! [NSManagedObject]
    } catch let error as NSError {
        print("Error While Fetching Data From DB: \(error.userInfo)")
    }

    tableView.reloadData()
}

上面的代码可以使对象保持删除状态,如果我离开视图然后返回,但是如果我重新启动应用程序,它们仍然会被删除 - 如果应用程序重新启动,我希望删除已删除的项目。

3 个答案:

答案 0 :(得分:3)

在我看来,你根本不是从CoreData删除对象。

companies.remove(at: indexPath.row) - 这里只需从获取的数据数组中删除对象

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

    //remove object from core data
    let context:NSManagedObjectContext = appDelegate.managedObjectContext!
    context.deleteObject(companies[indexPath.row] as NSManagedObject)
    context.save(nil)

    //update UI methods
    tableView.beginUpdates()
    companies.remove(at: indexPath.row)
    tableView.deleteRows(at: [indexPath], with: .fade)
    tableView.endUpdates()

    appDelegate.saveContext()
    }
}

答案 1 :(得分:1)

  

然而,当我导航到另一个视图控制器然后返回时,已删除的对象再次出现

当然,因为你没有采取任何措施来改变底层数据模型。

  如果我离开视图然后返回,

对象会保持删除状态,但是如果我重新启动应用程序,它们仍会被删除 - 如果应用程序重新启动,我希望删除已删除的项目

对不起,你为什么要这样?删除项目意味着删除它!也就是说,这意味着它将从基础数据模型中删除,这是核心数据数据库。你为什么要把死人复活?

在我看来,你真正的问题是核心数据是一个完全不合适的底层数据模型,用于你真正想要做的事情(不管它是什么)。核心数据不是初学者技术。我建议你放弃使用它。

答案 2 :(得分:0)

我认为您的第一个代码更接近您想要的内容。

最简单的行为是仅提取 ,从Core Data中删除并从表视图中删除以更新UI。这就是它,没有重新获取,没有重新加载。

OR

从核心数据中获取,删除,重新获取并重新加载表以查看用户界面中的更改。选一个!

如果你有一个数组作为中间数,你当然应该删除它。

现在,您不需要总是拥有一个数组(关于获取结果控制器的研究),您可以直接使用Core Data,但幸运的是,这正是您在这种情况下所需要的。

我的建议:获取核心数据仅一次以获取初始数据,将所有内容放入数组,使用数组进行操作,使其成为表的数据源并删除项中的数据数组和表格。因此,您的核心数据不会被删除,只会为您的工作阵列提供初始值。

对于插页,我想你想保留它们。如果您愿意,可以将它们保存到数组,表格和核心数据中。

最后一件事,你是在第一行代码中守护AppDelegate。如果您的应用程序正在运行,您肯定有AppDelegate,没有它,您的应用程序就无法运行,它会控制您的应用程序生命周期。你可能在遇到困境时遇到问题(很少但很可能)。保护上下文:

guard let context = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext else { 
     return
}

希望它有所帮助。