CoreData和Swift 3
最近,我一直在研究一个简单的任务管理器应用程序。 我决定快点编写它,因为我不想使用任何Pod,所以我从心爱的Realm切换到了CoreData,这就是我们旅程的起点。
CoreData与Swift 3一起对我来说还很陌生,因此我想阅读文档,但仍在Swift 2.2中。 那里没有问题,StackOverflow肯定会救我! 好吧,事实并非如此简单。 我花了几个小时才能找到所有资源并使其正常工作。 因此,我现在正在编写本教程,以便您可以在一个地方找到我发现的遍布互联网的内容。
- 将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%正常工作了!
在评论中留下您的问题;)
米哈尔