Tag: Coredata

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()使应用程序生成崩溃日志并终止。 尽管此功能在开发过程中可能很有用,但您不应在运输应用程序中使用此功能。 / * 出现错误的典型原因包括: *父目录不存在,无法创建或不允许写入。 *由于设备锁定时的权限或数据保护,无法访问持久性存储。 *设备空间不足。 […]

如何在NSManagedObject的单个实例上观察更改

在这篇文章中,我将描述如何观察单个NSManagedObject实例的变化。 我写这篇文章的动机是我的朋友,他问我: “您如何观察CoreData中单个对象的变化? 我知道这里有NSFetchedResultsController,但是值得只观察一个对象吗?!” 当然可以使用NSFetchedResultsController,但是它是为不同的事物创建的,如果您阅读文档,则可以找到以下内容: “您使用提取的结果控制器来有效地管理从Core Data提取请求返回的结果,以提供UITableView对象的数据。 (…)尽管可以以多种方式使用表视图,但访存结果控制器主要用于帮助您使用主列表视图。 ” 我的答案是-不要这样。 最有效的方法是观察NSManagedObjectContextObjectsDidChangeNotification 。 当上下文中托管对象的属性值更改时,将发布此通知。 userInfo词典包含以下键: NSInsertedObjectsKey , NSUpdatedObjectsKey和NSDeletedObjectsKey,NSRefreshedObjectsKey 。 如果已经熟悉此方法,则可以看一下我们的包装器,它可以避免编写样板代码。 我根据源代码做了要点,您可以在文章下面和此处找到源代码。 这是我们的观察者界面的样子: 它非常易于使用,您所需要做的就是创建CoreDataContextObserver实例并传递要观察的上下文: 让上下文= NSManagedObjectContext.defaultContext 让观察者= CoreDataContextObserver(context:context) 接下来,您需要传递将要观察的NSManagedObject实例,如果发生更改,您将在完成处理程序中获取有关该实例的信息: observer.observeObject(journal,completionBlock:{对象,状态为 打印(“更改:\(object.changedValuesForCurrentEvent())\ n”) 打印(“状态:\(状态)”) }) CoreDataContextObserver不仅限于一个对象,您可以观察到处于不同状态的许多对象,例如,如果您想了解日记帐删除,则将观察到。 删除状态: reader.observeObject(journal,state:.Deleted,completeBlock:{object,state in 打印(“对象已删除\ n”) }) 这样,您就可以以干净的方式跟踪NSManagedObject上的所有更改。 我在我们的github上创建了示例项目,您可以在其中使用CoreDataContextObserver。 我想说的是,如果您使用 func mergeChangesFromContextDidSaveNotification(_ notification :NSNotification!) 那么您将获得NSRefreshedObjectsKey中的更改。 因此,如果您想使用我们的观察员订阅此事件,将使用: reader.observeObject(journal,state:.Refreshed,completeBlock:{object,state in 打印(“刷新对象”) }) 如果您发现这些资源很有用,或者您是个很棒的人,请按 💚 。 […]

如何对CoreData模型进行单元测试(Swift)

测试持久性功能对我来说是一个大麻烦。 每次我启动测试时,我的模拟器都充满了测试元素。 我的记忆上下文 基本上,您可以简单地删除测试创建的任何内容,但是有一种方法更容易。 您可以添加“ 内存持久存储” 。 顾名思义,这是一个“内存中”存储。 当应用程序终止时,一切都消失了。 基本核心数据资料 为了了解正在发生的事情,我希望您解释一些核心数据基础知识。 托管对象模型是您在Xcode中创建的模型。 它描述了数据结构的实体。 该模型仅描述您的数据结构如何,不包含任何数据。 因此,在我们的测试用例中,我们想测试我们的业务逻辑是否可以与数据模型一起很好地工作。 因此,我们必须使用与生产中相同的模型。 让managedObjectModel = NSManagedObjectModel.mergedModel(来自:[Bundle.main]) 持久性存储协调器的作用类似于“持久性存储”的包装,而在大多数应用程序中,您通常只有一个持久性存储。 商店协调员知道数据结构。 让persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel:模型) 持久存储是数据的“存储”逻辑。 CoreData默认使用SQLite。 但是在我们的情况下,我们要使用“ In-Memory ”。 这意味着在我们的测试用例中,存储协调器具有一个(内存中的)持久存储。 persistentStoreCoordinator.addPersistentStore(ofType:NSInMemoryStoreType,configurationName:nil,at:nil,选项:nil) 被管理对象上下文是我们与之交互的类。 它处理所有众所周知的CRUD方法(创建/读取/更新/删除) 。 由于它就像商店协调器上的立面一样,我们只需要使用包含内存中商店的商店协调器创建一个新实例。 让ManagedObjectContext = NSManagedObjectContext(concurrencyType:parallelType)managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator 如果您仍然有一些问题不清楚CoreData的工作原理,我强烈建议您观看Cocoacasts的这段视频: Cocoacasts解释了核心数据栈 让我们看一下代码 这是“临时”存储的完整代码。 我的应用程序“ PursCreate”中使用的完整代码。 开始了。 该方法只是创建了一个我们可以与之交互的新上下文。 关闭应用程序后,您存储的所有数据都将消失。 现在,您可以测试持久层,而无需添加模拟器。

良好的iOS核心数据堆栈

我当时正在编写一个新的仅限iOS 10+的核心数据堆栈,并认为我将展示该过程变得多么简单。 数据协调员 我真的很想让一个人来管理核心数据堆栈。 传统上总是调用此CoreDataManager。 现在,将其命名为DataCoordinator。 最终课程DataCoordinator { 私有静态var协调器:DataCoordinator? 公共类func sharedInstance()-> DataCoordinator { 如果协调员==无{ 协调器= DataCoordinator() } 返回协调员! } 私人init(){ } } 3层架构 TL; DR跳至下一部分。 这不再是必需的。 现在我们需要设置一个核心数据栈。 我们需要有2个堆栈或2个上下文。 用于在主线程中读取和显示数据。 用于主要通过api调用和其他后台进程写入数据 这是通过使用3层体系结构来最佳实现的。 P1用于保存到持久性存储。 C1,C2是P1的子上下文。 C2用于从API写入。 以便将保存的更改快速传播到C1。 C1更改将传播到P1。 作为其子上下文。 传播速度很快,并且写入持久性存储的操作是在另一个上下文中进行的。 C1中的操作相当快。 这是建立3层架构的整体目标。 性能! 所有这些都不再需要设置。 NSPersistentContainer iOS 10引入了新的NSPersistentContainer类,该类将建立3层架构的所有样板代码减少到下面几行。 …公共变量容器:NSPersistentContainer 私人init(){ 容器= NSPersistentContainer(名称:“模型”) container.loadPersistentStores(completionHandler:{{_,error)在 如果让错误=错误{ fatalError(“未解决的错误\(错误)”) } }) } […]