CoreData和Swift 3

最近,我一直在研究一个简单的任务管理器应用程序。 我决定快点编写它,因为我不想使用任何Pod,所以我从心爱的Realm切换到了CoreData,这就是我们旅程的起点。

CoreData与Swift 3一起对我来说还很陌生,因此我想阅读文档,但仍在Swift 2.2中。 那里没有问题,StackOverflow肯定会救我! 好吧,事实并非如此简单。 我花了几个小时才能找到所有资源并使其正常工作。 因此,我现在正在编写本教程,以便您可以在一个地方找到我发现的遍布互联网的内容。

  1. 将CoreData添加到您的Xcode项目

答:简单的解决方案是在创建Xcode项目时仅选择CoreData。 Xcode将为您的AppDelegate文件添加所有必需的代码,还将为您创建.xcdatamodeld文件。 从这里跳到项目符号点2。

B.将CoreData添加到现有项目

这不是那么简单,但仍然很容易做到。 第一件事是打开您的AppDelegate文件,并在顶部导入CoreData 。 下一步是添加CoreData方法,如下所示:

  // MARK:-核心数据栈 
 懒惰的varpersistentContainer:NSPersistentContainer = { 
  / * 
 应用程序的持久性容器。 这个实现 
 创建并返回一个容器,并已为 
 应用到它。 该属性是可选的,因为有合法的 
 可能导致存储创建失败的错误条件。 
  * / 
  let container = NSPersistentContainer(name:“ tets”) 
  container.loadPersistentStores(completionHandler:{(storeDescription,error)在 
 如果让error = error as NSError?  { 
  //用代码替换此实现,以正确处理错误。 
  // fatalError()使应用程序生成崩溃日志并终止。 尽管此功能在开发过程中可能很有用,但您不应在运输应用程序中使用此功能。 
  / * 
 出现错误的典型原因包括: 
  *父目录不存在,无法创建或不允许写入。 
  *由于设备锁定时的权限或数据保护,无法访问持久性存储。 
  *设备空间不足。 
  *无法将商店迁移到当前模型版本。 
 检查错误消息以确定实际的问题是什么。 
  * / 
  fatalError(“未解决的错误\(错误),\(error.userInfo)”) 
  } 
  }) 
 返回容器 
  }() 
  // MARK:-核心数据保存支持 
  func saveContext(){ 
 让上下文= persistentContainer.viewContext 
 如果context.hasChanges { 
 做{ 
 尝试context.save() 
  } { 
  //用代码替换此实现,以正确处理错误。 
  // fatalError()使应用程序生成崩溃日志并终止。 尽管此功能在开发过程中可能很有用,但您不应在运输应用程序中使用此功能。 
 让nserror =错误为NSError 
  fatalError(“未解决的错误\(nserror),\(nserror.userInfo)”) 
  } 
  } 
  } 

创建所有.xcdatamodeld文件之后。 在应用程序的数据模型的上下文中调用它。 我称我为TaskManager.xcdatamodeld。 现在,您已经准备就绪,可以开始使用CoreData魔术了。

2.定义您的数据模型

打开您的.xcdatamodeld文件并创建一个实体并定义其属性。 我创建了具有许多属性的Task,例如,finish:Bool,taskDescription:String和uuid:String等。如果需要创建UIColor或未列出的其他Type,请简单地选择Transformable,然后将其用于UI元素只是将其检索为? UIColor

创建实体后,进入“编辑器”>“创建NSManagedObject子类”。 确保检查您的实体并点击创建。

既然我们已经定义了实体,我们要做的就是使用它! 给它保存一些数据,进行检索,更新,删除……命名!

既然我们已经定义了实体,我们要做的就是使用它! 给它保存一些数据,进行检索,更新,删除……命名!

3.保存数据

我喜欢做的事情,我认为众所周知的良好实践是将所有基于Entity的方法都放在一个类中,而不仅仅是在视图控制器中使用它。

在这种情况下,我有一个名为Tasks的类,所有事情都在那里发生。 重要的是,将它用作单例,而不要创建它的多个实例。 如果您不确定我的意思,只是用谷歌搜索,您也可以研究我的示例项目。 https://github.com/Majkitos/taskManager

保存数据非常简单。 首先是创建我们的环境。

  let context =(UIApplication.shared.delegate as!AppDelegate).persistentContainer.viewContext 

下一步就是简单地用我们的上下文创建Task类型的常量。 比起将数据保存到其中并从AppDelegate执行saveContext()方法而言。 就我而言,它看起来像这样:

  func addTask(描述:字符串,日期:完成的日期:布尔,类别:整数,uuid:字符串){ 
  let task = Task(上下文:上下文) 
  task.category = Int32(类别) 
  task.date =日期 
  task.finished =完成 
  task.taskDescription =说明 
  task.uuid = uuid 
  task.notificationEnabled = false 
  (UIApplication.shared.delegate为!AppDelegate).saveContext() 
  } 

4.检索数据

现在,我们已经永久保存了数据,但是要在我们的应用程序中显示它们,我们需要从存储中检索它们。

我的Task类中有一个Task类型的数组,并用它来保存数据。 要从存储中获取数据,请使用以下获取方法。 同样,将您的课程作为单例使用也很重要!

  func taskData()-> [任务] { 
 做{ 
 任务=尝试context.fetch(Task.fetchRequest()) 
  }赶上{ 
  print(“从CoreData提取数据时出错”) 
  } 
 退货任务 
  } 

5.删除数据

无法删除数据而保存数据将毫无用处,因此这里介绍如何删除数据

首先是检索数据,然后选择要删除的正确对象。 我将UUID用作我创建的每个任务的唯一标识符。 这样,我可以轻松地确定需要删除或编辑的任务。 我正在for循环中过滤给定uuid的任务:

  func deleteTask(withUUID:String){ 
  let request = NSFetchRequest (entityName:“ Task”) 
 做{ 
 让searchResults =试试context.fetch(request) 
 用于searchResults中的任务{ 
 如果task.uuid == withUUID { 
  //删除任务 
  context.delete(任务) 
  } 
  } 
  } { 
 打印(“请求错误:\(错误)”) 
  } 
  (UIApplication.shared.delegate为!AppDelegate).saveContext() 
  } 

6.更新数据

当然,最后一件事是如何更新数据。 我经常在更新任务的完成属性。 因此,我创建了一种方法来快速执行此操作。 它与deleteTask()方法非常相似。 您再次检索所有任务数据,使用for in循环对其进行过滤,找到具有选定uuid的任务后,将更新所有要更新的内容,并将所有更改保存到上下文中。 轻松地柠檬榨汁。

  func updateTask(uuid:String,isFinished:Bool){ 
  let request = NSFetchRequest (entityName:“ Task”) 
 做{ 
 让searchResults =试试context.fetch(request) 
 用于searchResults中的任务{ 
 如果task.uuid == uuid { 
  task.finished = isFinished 
  } 
  } 
  } { 
 打印(“请求错误:\(错误)”) 
  } 
  (UIApplication.shared.delegate为!AppDelegate).saveContext() 
  } 

好吧,就在那里! 使用Swift3的CoreData。 您可以在这里检查我的示例项目:https://github.com/Majkitos/taskManager。 这里只有一个音符。 在撰写本文(31.10.16)时,该项目尚未100%完成,一旦完成,我将提交所有更改。 我目前正在完成通知,由于内存泄漏,我需要进一步调整导航。 但是,对于CoreData来说,它已经完成并且100%正常工作了!

在评论中留下您的问题;)

米哈尔