Tag: 核心数据

与CoreData Swift 3结合使用以接受文本和URL的共享扩展

正如我在先前有关操作扩展的博客中提到的那样,我正在创建默认Apple Notes应用程序的副本,其中还包括创建共享扩展名,该共享扩展允许我的Notes应用程序接受其他应用程序中的URL和文本。 这里的主要挑战是,我希望我的共享扩展名能够创建或添加到保存在CoreData中的现有笔记中。 整个项目可以位于此处(免责声明,我仍在对其进行调整): almusto / CustomNotes 通过在GitHub上创建一个帐户为CustomNotes开发做出贡献。 github.com 我做了很多的在线查找工作,但从未真正找到一个很好的例子说明我正在尝试做的事情。 其中一些方法包括在CoreDataStack的init中使用NotificationCenter并使用它来传递数据的方法,但是我发现了一种更简单且似乎很好的方法! 就像所有其他扩展程序一样,Share Extensions基本上是它们自己的应用程序,但是它们需要作为项目的一部分而不是独立的项目包含在内。 要在项目中创建共享扩展名,请转到文件->新建->目标,然后选择共享扩展名。 创建后将出现一个弹出窗口,询问您是否要使其激活。 这意味着在构建应用程序时,它将构建扩展而不是应用程序。 您可以选择否或是,然后手动更改要在Xcode左上方运行的内容: 如前所述,我在Notes应用程序中进行了股票扩展。 为了使这两个应用程序彼此通信,首先要做的是将您的应用程序和扩展名连接到同一应用程序组。 为此,请转到项目功能,然后将您的应用程序和扩展程序的“应用程序组”都打开,然后将它们添加到同一组中: 在共享扩展本身中,您会注意到它带有类型为SLComposeServiceViewController的ShareViewController,其中具有三个函数: isContentValid()->布尔 didSelectPost() configurationItems()-> [任何]! 为了解释这些功能,您可以使用Safari快速运行扩展,然后单击活动按钮时,应该看到扩展已加载,如下所示: 在不编写任何代码的情况下单击它之后,您将看到此消息: 如您所见,它就像是Safari中自己的小应用程序。 回到您可能已经猜到的三个函数,当您单击发布按钮时,didSelectPost()被触发。 isContentValid()实际上是在检查我们尝试与应用程序共享的内容是否为正确的类型。 此功能确定是否启用发布按钮。 最后,configurationItems()函数使我们能够将信息发布到特定对象。 在此示例中,我希望能够通过Core Data在CustomNotes应用程序中创建或添加到现有笔记中。 在开始在扩展程序中编写代码之前,让我们回到我的customNotes应用程序以提供一些上下文,并开始与扩展程序共享coreData的过程。 Core Data上还有其他资源,因此除了与共享扩展有关的需求之外,我将不做过多介绍。 我个人喜欢创建一个可以处理我所有核心数据需求的核心数据栈。 在此示例中,我的数据模型称为“ NotesModel”,它具有“ Note”类型的实体和两个属性。 一个叫做String的“ title”,另一个叫做Date的“ date”,在CoreData中实际上是NSDate类型。 以下是我的CoreDataStack: 现在,在此示例中,我只想允许我的notes应用程序接受URL和文本。 第一步是进入扩展程序的plist文件,并将NSExtensionActivationRule更改为字典,然后将NSExtensionActivationSupportsWebPageWithMaxCount作为数字添加为1,将NSExtensionActivationSupportsText作为布尔值添加为YES。 同样,当我们在这里时,您可以将Bundle显示名称更改为所需的名称,因为此名称是设置活动控制器时实际显示的名称。 现在,在我们的ShareViewController中,我们创建一些变量来保存数据。 一方面,我希望变量保留我的网址信息,在我的示例中,我只希望该网址为字符串。 另外,如果我只是想共享文本,我希望有一个变量可以保留该文本。 一定要在底部启用这个小的选择注释选项,我们需要使用我们的configurationItem函数,但是我们想用CoreData中的注释填充它,因此让我们向ShareViewController添加一些属性。 一个用来存储我们所有的笔记,一个用来创建我们的CoreDataStack实例,另一个用来保存我们选择要发布到的笔记的值。 var selected注意:注意! […]

移动数据库优化:领域与SQLite

在这个故事中,我将告诉您我们如何开发结构化方法来解决复杂的技术问题,并成功地将应用程序的性能提高了30倍。 我们开始收集具有技术要求的新企业应用程序的开发。 最初,我们发现我们的应用程序应包含以下主要功能: 包含图表的报告 一个简单的任务跟踪系统 公司全体员工名单 所有这些数据也应可供脱机使用。 听起来不太难,对吧? 我们是这样认为的。 我们基于JSON进行了客户端与服务器之间的交互,并基于SQLite进行了脱机数据在移动设备上的存储,从而获得了最初的技术堆栈。 在iOS上,我们使用了几年前非常流行的CoreData包装器MagicalRecord。 今天,这绝对是一个错误的选择,因为它是用Objective-C编写的,并且在过去3年中没有任何更新。 但是,在2014年,它是免费的,开源的,并且在GitHub上拥有1万颗星,但是主要原因是缺少其他选择。 在Android上,出于相同的原因,我们决定使用ORMLite。 在开发过程的早期,一切都很好。 我们的开发服务器上有一些演示报告和数十名员工。 但是,在将产品卖给第一个客户之后,我们就遇到了严重的性能问题。 后端团队的同事将客户生产数据库的一部分导入了我们的测试环境。 而且我们发现我们的应用尚未准备好与20万名员工一起使用。 下载完整列表花费了5到10分钟,滚动性能很差,搜索根本不起作用。 这不是我们最终用户所期望的。 另一个问题是报告。 其中一些包含具有数百万个点的图表,因此我们遇到了同样的问题:两个平台上的下载速度缓慢且性能不佳。 我们试图进行一些修复,将分页引入客户端-服务器请求并将批处理写入本地数据库,但是我们无法将性能提高得足够高。 对我们来说幸运的是,我们的销售部门与客户签订了长达6个月的合同,第一部分是更新一些内部系统,因此我们需要一两个月的时间来解决问题。 我们了解到,我们需要对发生的问题进行全面研究,而不是编写混乱的错误修复程序。 下面我将详细介绍我们的方法。 这项研究 我们从优化员工名单绩效开始。 经过几次快速修复错误的失败尝试之后,我们决定将下载员工列表并将其显示在UI中的过程分成较小的步骤,并测量每个步骤的持续时间,以找出需要解决的问题。 最后,我们发现等待服务器响应(30秒)并写入本地数据库(5-10m)是整个过程中最长的两个部分,而其他部分仅花费了几百毫秒,因此不需要注意。 服务器响应 在进行任何优化之前,我们只需要下载一次完整的员工列表即可。 之所以选择这种方法,是因为此列表的任何一部分对最终用户都没有任何价值。 没有人希望看到姓氏以字母A开头的员工。我们的用户需要完整的列表才能访问所有联系人并执行离线搜索。 我们还具有喜欢的联系人功能,可通过我们的服务器在用户设备之间进行同步。 首先,我们将喜欢的数据移动到本地数据库中的单独请求和单独表中。 那并没有给我们带来巨大的性能提升,而是让我们在服务器端启用完整员工列表的内存存储。 响应时间优化的最后也是最重要的部分是引入增量更新。 如上所述,我们在服务器端将完整的员工列表存储在内存中。 它将响应时间从大约30秒减少到仅1-2秒,由于网络延迟,我们无法再将其缩短。 与后端和销售团队讨论了我们的解决方案之后,我们还发现员工名单通常每天仅可以更新一次,因此无需进行更频繁的更新。 因此,为了减少服务器端的负担并加快移动客户端上的数据库写入速度,我们引入了增量更新。 首次安装后,我们的应用程序立即下载完整列表,但第二天它要求服务器进行一次小的增量更新,以提供最新数据应用程序的版本(时间戳)。 本地数据库优化 增量更新极大地减少了员工列表更新时间。 但是,我们仍然有两个问题: 由于SQLite的写入速度,初始加载太慢 由于完全相同的原因,应用少量增量更新(例如,在两周不活动之后)也花费了很多时间 在批量编写没有提高性能之后,我们决定尝试其他方法。 我们有一个假设,在我们的案例中,SQLite或MagicalRecord都是瓶颈。 因此,我们提出了两种可能的解决方案: 切换ORM 与其他数据库切换SQLite 我们没有找到MagicalRecord的替代品,因此决定使用CoreData。 […]

核心数据的构建块

Core Data是Apple开发的框架。 它于2005年首次用于Mac OS。 后来它于2009年在iOS上可用。我相信,现在它是最可爱的框架。 好吧,正如我提到的,核心数据是一个框架。 它还是一个对象图管理器。 它曾经将数据持久存储在磁盘上。 对象图不过是相互连接的对象的集合。 核心数据栈 核心数据堆栈不过是三个关键对象的集合,这些对象负责处理所有外部数据存储。 托管对象模型 托管对象上下文(MOC) 持久性商店协调员 托管对象模型 托管对象模型是NSManagedObjectModel类的实例。 它用来表示核心数据应用程序的数据模型。 这是初始化Core数据堆栈时的第一步。 初始化时,这通常会先加载到内存中。 资料模型 数据模型是应用程序捆绑包中的文件,其中包含应用程序的数据架构。 正如您在图1中看到的那样,受管对象模型与数据模型相连。 持久性商店协调员 持久性存储协调器是NSPersitentStoreCoordinator类的实例。 它在核心数据堆栈中起关键作用。 它在Core数据堆栈中的Managed Object Model之后被实例化。 因此,它对托管对象模型及其结构(具有模型对象)具有清晰的了解。 它保留每个模型对象的引用。 如图1所示,持久性存储协调器与托管对象模型,MOC和持久性存储连接。 因此,可以说,持久存储协调器是连接所有边缘的桥梁。 我们的应用程序中可以有多个MOC和多个持久性存储。 但是很少有多个持久性协调员。 它将多个持久性存储作为单个聚合持久性存储呈现给MOC。 托管对象上下文 托管对象上下文(MOC)是NSManagedObjectContext类的实例。 MOC可以创建,读取,更新和删除模型对象。 是我们经常互动的实例。 如您所见,这与持久性存储协调器有关。 MOC通过持久性存储协调器获取模型对象。 如前所述,我们可以拥有多个MOC。 好吧,这是核心数据的高级主题,我将在另一个故事中对此进行讨论。 受管对象上下文就像一个便笺本。 它通过从持久性存储,持久性存储协调器以及我们要存储的数据中捕获数据来创建模型图。 现在,您可以根据需要修改这些数据。 除非您将更改保存在持久性存储中,否则持久性存储将不了解更改。 NSPersistentContainer iOS 10中引入了NSPersistentContainer。此容器具有核心数据堆栈,并提供可使用的MOC。 因此,在使用它之前,您应该了解核心数据栈。 好吧,我想是时候进入代码了。 让我们看看核心数据是如何工作的。 演示版 让我们开始一个新的单视图应用程序并检查核心数据模块。 […]

不要以编程方式创建核心数据模型!

当我决定分析我的代码生成时,我在最新,最出色的项目上工作效率很高。 我的大多数方法都在6毫秒以下才能编译,但某些布局方法却需要20毫秒或20毫秒以上的事实,这让我感到非常恼火。 一旦删除了第三方布局框架,并构建了自己的优化解决方案,我就认为自己将恢复生产效率。 然后,我注意到我的图形被构建为PNG,并占用了不必要的空间。 那让我很生气。 一旦将肿的图形移动到矢量上,然后将这些矢量移动到代码上,并且一旦制定了自定义二进制矢量资产格式,以使我的图形不会减慢编译时间,那便是我决定终于可以恢复生产力。 在构建应用程序中的下一个屏幕时,每次在iPhone上运行该应用程序时,我都会不断看到相同的3秒进度条。 “复制领域框架”。 那让我很生气。 为什么浪费时间复制价值95 MB的框架? 因此,随着Realm进入斩波阶段,它将被Apple的数据库基础解决方案Core Data取代。 Core Data随附了一个漂亮的UI,该UI已直接集成到Xcode中,这使创建数据库模式变得容易。 不仅如此,您还可以添加映射模型,从而可以轻松地将架构迁移到新版本。 但是我很喜欢Realm的架构都是用代码定义的,所以我愚蠢地决定着手建立一个类似的解决方案。 有一些稀疏的文档可以在代码中定义模式,但是可以做到。 而我做到了。 没关系 然后我想添加迁移。 那是问题出现的时间。 我开始遇到各种有趣的错误。 您是否知道Google上没有“不支持的实体映射类型”的搜索结果? 我很遗憾。 我搜寻了和我一样处境的人们的互联网。 没有太多可找到的。 不仅如此,当我确实找到那些决定以这种方式使用Core Data的人的参考文献时,有很多人表达了自己的困惑。 出于好奇,用代码而不是用数据模型编辑器构建模型的背后原因是什么? […]如果是由于视力障碍[…] –困惑的CocoaBuilder.com用户[链接] 最终,我确实弄清楚了迁移。 部分归功于使用称为Hopper的有用调试工具检查了错误原因。 现在,我可以恢复生产力了。 因此,正如标题所述,不要以编程方式创建Core Data模型。 但是,如果您要采取任何方式,我的源代码可能会有所帮助。

CoreData? 难以学习,应用有趣

我只是在NSManagedObject和NSManagedObjectContext之间徘徊,因为我的程序无法正常工作。 情况是我需要利用Apple提供的CoreData框架进行简单的CRUD操作。 该文档非常有用,丰富且清晰,但对于我作为新开发人员而言并不适用。 我的第一个想象是CRUD操作将涉及具有简单语法的简单步骤,例如将某些内容保存在UserDefaults中。 我们需要定义一个值和一个键来实现持久性。 但是CoreData确实使我陷入了总共3天的混乱代码。 我们需要定义PersistenceStore(无论是什么名称,我都不想提及它的确切名称。哈哈哈),ManagedObjectContext以及保存涉及线程相关性和并发性的过程。 真的让我不知所措。 带给我很多注释和代码的其中一件最重要的事情是ManagedObjectContext的用法。 为了第一。 我只是学习如何将对象保存到磁盘。 由于每当执行保存业务逻辑时都会更新我的SQLite文件,所以我不在乎该错误。 根据Apple本身的说法,故障是为了节省内存使用而设计的,因为该对象保持为零状态,直到触发该对象才占用任何内存。 不完全是描述,而是理解概念的最简单方法。 以我为例,当我需要显示数组中包含的对象以更新TableView时,会导致混乱。 由于这个错误,我的tableView仍然不显示任何列表,但行数与数组数完全相同。 事实证明,我的代码中缺少什么,我没有正确使用ManagedObjectContext。 我插入了privateManagedObjectContext内的ManagedObject,当我读取该属性时,从mainManagedObjectContext调用它。 因为前者在函数返回时被释放,所以我的ManagedObject再次回到其故障状态。 值得注意的是: 照顾好ManagedObjectContext,您的代码就可以了。 附录: 我还有更多问题,其中之一是线程安全问题。 我会学习,我会克服它。 这些错误会使我屈膝。 😀

核心数据与NSKeyedArchiver与用户默认值

核心数据,NSKeyedArchiver和UserDefaults是程序员在应用程序启动之间可以持久保存数据的三种方式。 尽管核心数据稍微复杂一些,但是当存储的信息需要结构时,它很有用。 与核心数据相比,NSKeyedArchiver不太复杂且运行速度较慢,但​​使用起来却简单得多。 UserDefaults是保存数据的最简单方法。 核心数据 核心数据的主要好处包括: 有效查询的能力 数据的结构使得每个实体都具有某些属性(考虑具有特定类型的属性),并且可能通过关系也可能不与其他实体相关 自动迁移-基本上,这仅意味着当您创建核心数据模型时,即会创建一个SQLite数据库。 如果随后更改数据模型(例如,向数据模型添加更多属性),则新数据模型与原始持久性存储不兼容。 Apple为我们处理了从一种数据模型版本到另一种数据模型版本的“迁移”-感谢Apple! 在深入研究代码之前,首先让我们看一下一些定义: NSPersistentContainer负责读取/写入核心数据。 类型为NSManagedObjectContext的viewContext。 您可以通过NSManagedObjectContext创建核心数据对象的实例。 为了将核心数据集成到您的项目中,您必须首先创建一个核心数据.xcdatamodel文件。 在此文件中,您将定义要保留的实体,包括每个实体的属性。 创建.xcdatamodel文件后,然后将一个新的.swift文件添加到项目中,该文件将包含代码数据的所有样板代码。 以下代码中需要注意的三件事- NSPeristentContainer名称必须与.xcdatamodel文件相同。 我创建了一个单例,以便在应用程序的整个过程中只有一次通过核心数据保存的信息实例。 如果您总体上对单例/设计模式感到好奇,请查看此博客。 不要忘记将CoreData导入.swift文件! *如果创建一个新项目并选择向该项目添加核心数据,则上面的样板代码将显示在App Delegate中。 除了保存数据之外,您还可能希望获取该数据以在应用程序下次启动时填充您的应用程序。 假设您在.xcdatamodel文件中创建了一个名为“ Book”的实体。如下面的代码所示,您可以使用NSFetchRequest来获取数据。 我创建了一个名为“ Books”的数组,该数组等于[Book](),表示Book实体的数组。 每当我想用此保存的数据填充我的应用程序时,我都会调用此CoreDataModel.sharedInstance.fetchWorkoutData()函数,并将要使用的数据设置为等于CoreDataModel.sharedInstance.books。 从核心数据中删除信息也非常简单-您所需要做的就是获取存储的信息并遍历数组,并从持久性容器中删除每个对象。 瞧! 我没有在这篇文章中深入研究关系,但是下面的博客将深入研究核心数据中关系的代码。 NSKeyedArchiver NSKeyedArchiver提供了直接与磁盘交互的功能。 具体来说,它将序列化NSCoding,这是一种具有两种方法的协议: 编码(使用aCoder:NSCoder) 初始化?(编码器aDecoder:NSCoder) 在下面的示例中,我的目标是保留[Person]数组。 类Person具有两个属性:firstName(字符串类型)和lastName(字符串类型)。 从下面的代码中可以看到,Person类采用并符合NSCoding协议。 通过NSKeyedArchiver存储和检索数据非常简单。 当您想存储信息时,可以仅调用NSKeyedArchiver.archiveRootObject -这是一个内置方法。 同样,当您要检索持久数据时,可以调用另一个内置函数NSKeyedUnarchiver.unarchiveObject。 如您所见,NSKeyedArchiver比Core Data实施起来简单得多,并且是持久保存数据的诱人选择。 用户默认值 UserDefaults是一个类,允许简单存储不同的数据类型。 它主要用于存储少量数据,以在应用程序启动或设备重新启动之间持续存在。 UserDefaults可以存储基本类型(bool,float,double,int等)和更复杂的类型(数组,字典)。 尽管UserDefaults没有结构,但据说它比核心数据要快,因为它只是键值对。 由于它没有结构,因此存储不需要结构的数据很有用,因此不需要用户偏好。 需要注意的一件事是,如果您重置一个键,那么无论两个键是否都必须相同,如果一个键具有所有小写字母,而第二个键具有一个大写字母,则现有数据将不会被替换。

在iOS App中使用核心数据背景上下文获取远程数据

核心数据是Apple提供的用于开发iOS应用程序的对象图和持久性框架。 它处理对象生命周期,对象图管理和持久性。 它支持用于处理应用程序内部模型层的许多功能,例如: 对象之间的关系管理。 使用撤消管理器更改跟踪 延迟加载对象和属性 验证方式 使用NSPredicate进行分组,过滤和查询 模式迁移 使用SQLite作为后备存储的选项之一。 Core Data自动提供了许多高级功能,它具有陡峭的学习曲线,可供开发人员首次学习和使用。 在iOS 10之前,要在我们的应用程序中设置Core Data,我们需要执行许多配置和样板代码来构建Core Data Stack。 幸运的是,在iOS 10中,Apple引入了NSPersistentContainer,我们可以使用它初始化所有堆栈并以很少的代码获得NSManagedObject上下文。 在本文中,我们将构建一个简单的演示应用程序,该应用程序可从远程《星际大战》 API获取电影列表,并使用后台队列天真地在没有同步策略的情况下同步Core Data存储中的数据。 我们将建立: 受管对象模型架构和影片实体。 电影实体的托管对象。 CoreDataStack:负责使用该模式构建NSPersistentContainer。 ApiRepository:一个类,负责使用URL会话数据任务从StarWars API中获取电影数据列表。 DataProvider:一个类,提供接口以从后台存储库中使用NSManagedObjectContext从数据存储库中获取电影列表并将其同步到Core Data存储。 FilmsViewController:与数据提供者进行通信并使用NSFetchedResultsController从核心数据视图上下文中获取并观察更改的视图控制器,然后在UITableView中显示电影列表。 您可以在项目GitHub存储库中签出该应用程序的完整源代码。 alfianlosari / CoreData-Fetch-API-Background 使用核心数据背景上下文获取Star Wars API的iOS应用– alfianlosari / CoreData-Fetch-API-Background github.com 您还可以通过单击以下网站的链接来结帐并尝试使用StarWars API。 SWAPI –星际大战API 星球大战(Star Wars)API或“ swapi”(Swah-pee)是世界上第一个量化且可通过编程访问的数据源…… swapi.co 受管对象模型架构和影片实体 我们将执行的第一步是创建包含影片实体的托管对象模型架构。 从Xcode创建新文件,然后从核心数据模板中选择数据模型。 将文件命名为StarWars,它将以.xcdatamodeld作为文件扩展名保存。 单击我们刚刚创建的数据模型文件,Xcode将打开数据模型编辑器,在其中我们可以将实体添加到托管对象模型模式中。 […]

Swift中的NSBatchUpdateRequest及其优势

在此博客中,我们将学习实现NSBatchUpdateRequest Swift 3.x版本在iOS 8中引入的Core Data的说明。 我们还将关注内存使用情况和执行时间。 我还制作了有关此主题的视频教程。 请检查博客末尾的链接。 从iOS 8和更高版本以及OS X Yosemite和更高版本,我们可以直接与持久性存储进行交互并更新属性。 根据Apple的说法,这是批量更新。 因此,在不浪费更多时间的情况下,让我们深入了解Xcode中的代码部分。 创建一个新项目,并确保选中使用核心数据复选框。 创建项目后,转到。 xcdatamodeld文件并创建一个名为Student的实体。 我们还将创建它的两个属性, studentName和studentRollNo 。 每当我们尝试从编辑器创建NSManagedObject类时,在Swift 3.x中都会出现一个奇怪的错误- 具有相同名称的文件名redeclaration 。 因此,为了解决该问题,请选择实体,然后在“ 数据检查器”部分中转到“ 类” 。 如下图所示,将Module更改为Current Product Module ,将Codegen为Manual / None 。 然后,最后单击“编辑器”,然后单击“ 创建NSManagedObject子类”。 因此,我们已经准备好模型子类。 在这里,它们看起来像。 Student + CoreDataClass.swift 进口基金会 导入CoreData 公共班学生:NSManagedObject { } Student + CoreDataProperties.swift 进口基金会 导入CoreData 扩展学生{ @nonobjc公共类func fetchRequest()-> […]

NSFetchedResultsController问题

编者注:本文最早在iOS 10发行之前发布。Apple自那时以来对CoreData进行了重大更改: NSPersistentContainer现在可以用作标准的Core Data堆栈。 您可能已经注意到的另一个更改是对本文所述的NSFetchedResultsController的长期问题的修复。 尽管iOS的采用率很高,但某些设备仍在运行存在NSFetchedResultsController问题的iOS 9版本。 因此,本文仍然与今天的iOS开发人员相关。 NSFetchedResultsController NSFetchedResultsController是iOS核心数据开发的主要内容。 在iOS 3中引入的此类负责有效管理Core Data实体的集合。 在过去的六年中,我在所有类型的Core Data堆栈配置中都使用了该控制器。 在针对Black Pixel顶级客户之一的最新项目中,我们决定使用标准的“兄弟”核心数据堆栈配置: 一个 NSFetchedResultsController用于从主UI上下文中的商店中获取对象。 此主要上下文仅用于从商店读取。 用于从服务器检索实体的后台上下文已连接到持久性存储协调器,作为主UI上下文的同级对象。 设置主上下文时,只要后台上下文将其更改保存到存储中,就会自动合并来自后台上下文的更改。 令我惊讶的是,我最终遇到了一些奇怪的问题,即NSFetchedResultsController有时与商店的内容不同步:某些与NSFetchedResultsController的谓词匹配的现有实体将永远不会被获取。 如此基本和预期的事情将如何发生? 一些解释和修正 快速的Google搜索产生了很多答案。 特别是其中一个详细说明了NSFetchedResultsController如何进行。 这是给出的说明(注意:FRC = NSFetchedResultsController ): 1.使用与所有对象都不匹配的谓词设置FRC(从而防止将与谓词不匹配的对象注册到FRC上下文中)。 2.第二个上下文更改了一个对象,这意味着它现在与FRC的谓词匹配。 保存第二个上下文。 3. FRC的上下文处理 NSManagedObjectContextDidSaveNotification 但仅更新其注册的对象。 因此,它不会更新现在与FRC谓词匹配的对象。 4.保存时FRC不会执行另一次提取,因此它不知道应该包含更新的对象。 我对第三点的发言感到不安。 这是建议的修复程序: 解决方案是在合并通知时获取所有更新的对象。 这个想法是在NSManagedContextDidSaveNotification userInfo有效内容的一部分的每个更新对象上调用refreshObject(_:mergeChanges:) 。 另一组说明(例如,文章“ Core Data Gotcha”和“带谓词的NSFetchedResultsController忽略了从不同NSManagedObjectContext合并的更改”)提到当NSManagedContextDidSaveNotification 被触发时,某些对象可能是主上下文中的故障,因此需要在调用mergeChangesFromContextDidSaveNotification()之前触发这些故障。 这里的想法是在NSManagedContextDidSaveNotification userInfo有效内容一部分中的每个更新对象上调用willAccessValueForKey(nil) 。 然后调用mergeChangesFromContextDidSaveNotification() […]

使用CoreData创建待办事项列表应用程序的简便方法

如果初学者和高级程序员有什么共同点,是我们希望事情简单明了吗? 没有功能或效率的折衷 核心数据是一个非常有用的框架,它使开发人员能够在设备上本地管理数据。 尽管有用且非常强大,但是对于初学者来说,这尤其令人恐惧,尤其是在处理诸如NSManagedObject和NSPredicate NSManagedObject对象时。 当我们只想管理数据时,对于经验丰富的开发人员来说也可能会很费力。 CoreDataBC解决了这个问题; 基于核心数据构建的高级框架。 它可以解决您必须解决的大多数麻烦,并使开发人员更轻松地交互和管理其数据模型。 这就是框架的简单性。 // 保存数据 self.coreData.pushSingleValue([“ ”:]) //检索数据 self.coreData.retrieveData() //获取数据 let coreDataRecords = self.coreData.getData()//返回NSManagedObject的数组 //更新数据 如果让recordToUpdate = coreDataRecords.first { self.coreData.update(recordToUpdate,[“ ”:] } 如果您想要有关该框架的更多信息,请参阅GitHub文档。 在本教程中,我将演示如何使用CoreDataBC创建一个简单的待办事项列表 应用程序 。 没什么复杂的,只是一个简单的UITableView将显示一些数据,一个添加到列表中的按钮以及滑动操作以将其标记为已完成和删除。 先决条件 您应该至少在UITableViews中具有一些背景知识,并已安装CocoaPods。 如果您尚未安装CocoaPods,请参阅CocoaPods安装指南。 如果您正在阅读本文,那么我假设您已经对UIKit框架以及Swift有了很好的理解。 最后说明:一切都会以编程方式完成,只是增加了挑战。 项目设置和安装 创建一个新的Single View Xcode项目,并选中“ Use Core Data并打开终端。 暂时关闭Xcode项目,并在终端中将CD插入Xcode项目目录并初始化pod。 荚初始化 这样,您的项目目录中将有一个名为Podfile的新文件。 在文本编辑器中打开文件,然后在其下方显示“#Pod # Pods for 添加CoreDataBC pod。 […]