Tag: 核心数据

破解核心数据测试

核心数据是一个框架,它隐藏诸如对象生命周期和对象图管理之类的持久层的逻辑,以帮助您以高级方式管理模型层对象。 是的,Core Data对许多开发人员来说都是有争议的。 但是,它仍然是有用的框架:性能良好,并且得到Apple的支持。 关于核心数据的单元测试,有很多不错的文章,但是大多数文章集中在模拟上下文。 由于发布了持久性容器类NSPersistentContainer,因此越来越难以模拟上下文并将测试写入容器。 因此,在本文中,我将探讨一个新主题:为NSPersistentContainer编写测试,增强型核心数据。 我们将一起使用NSPersistentContainer设置核心数据堆栈,并为此编写测试。 TL; DR 我们将学习如何: 使用NSPersistentContainer构建核心数据栈 使用内存永久存储 引入两个测试双打:“假”和“存根” 做一个异步测试 先决条件 迅捷3 Xcode 8 核心数据基础知识 iOS 10(由于我们将使用NSPersistentContainer,因此需要iOS 10)。 以下是一些有关核心数据的好文章: 完整的核心数据应用程序(代码在Objective-C中,但是概念相同) 核心数据入门教程 我们的任务 现在,我们有一个简单的任务:实现待办事项列表系统,在其中我们可以创建,读取,更新和删除待办事项(CRUD)。 而且这个待办事项系统应该永久保存数据,以便即使我们终止应用程序也可以稍后获取它们。 因此,我们需要实现这些方法: 创建待办事项 提取所有待办事项 删除待办事项 提交对永久存储的更改 由于我们只想在需要时执行保存,因此我们不会在创建/编辑/删除方法中将NSManagedObjectContext .save()视为副作用。 相反,我们将其设为独立方法。 当用户按下“保存”时将允许保存数据,或者当用户离开当前视图时将其保存。 尽管通过使用NSPersistentContainer在iOS 10之后设置Core Data堆栈更容易,但最好具有一些基本知识。 我们将在以下各节中采用这些概念。 因此,在下一节中,我将简要介绍Core Data堆栈。 核心数据栈 根据苹果公司的说法,核心数据栈是框架对象的集合,这些对象是核心数据初始化过程的一部分。 核心数据堆栈中包含4个基本组件: 托管对象上下文 (NSManagedObjectContext):为托管对象提供便签本 持久性商店协调器 (NSPersistentStoreCoordinator):汇总所有商店 托管对象模型 (NSManagedObjectModel):描述商店中的实体 持久对象存储 :包含已保存的记录。 […]

在Xcode Playground中使用CoreData

Xcode Playground是一个功能强大的工具,可以测试您的Swift代码并编写整个框架。 它使您能够实时检查代码结果并进行快速更改。 Apple Swift 4游乐场提供了练习使用的示例,您可以在其中查看使用这种可爱语言编写的新内容。 在应用程序中开发Core Data时,您可能会考虑数据流并尝试构建一些数据堆栈,这可能会在不久的将来缩短您的开发时间。 您可以在Xcode游乐场中完成所有这些操作,但是有一些限制。 首先也是最重要的一点是,您不能在操场上使用NSManagedObject子类,而必须使用KVO对Core Data实体执行操作。 您必须记住的第二件事是,每次更新数据模型时,也需要更新游乐场资源。 让我们从向项目添加数据模型开始: 现在用一些行填充模型: 保存并构建应用程序。 下一步是将Playground添加到您的Xcode项目中,无论如何我还是更喜欢这样做,因为我认为这是测试服务调用,模型初始化等的理想场所。 如果您的项目中已经有Playground,请在Xcode树中打开“产品”文件夹,右键单击.app文件,然后单击“在Finder中显示”。 接下来,右键单击打包文件,然后单击“显示打包内容”。 之后,将.momd文件移动到Playground Resources文件夹 就是这样! now您现在可以在操场上使用数据模型! 重要说明:如前所述,如果您更改数据模型,则需要再次执行此步骤,只需更新Playground Resources中的.momd文件即可。 最后,将以下代码添加到操场上并开始播放! 👌🏽 结论 如您所见,在Playground中使用Core Data很简单,但是您必须牢记此解决方案的限制。 无论如何,从现在开始,您已经分离了“沙盒”以通过实时预览快速构建和测试数据堆栈! 😋另外,您可以基于真实的应用程序模型测试查询和其他操作,而不会影响主数据模型! 谢谢阅读! 😁

如何编写核心数据的单元测试用例

在本教程中,您将了解如何在Xcode中构造Core Data Stack来测试您的Core Data应用程序。 这并不是应该的那么简单,因为大多数测试将取决于有效的核心数据堆栈。 您不想破坏单元测试中的数据,以免干扰您自己在模拟器或设备上进行的手动测试。 访问控制 默认情况下,swift中的类具有“内部”访问级别。 这意味着您只能从它们自己的模块中访问它们。 由于应用程序和测试位于单独的模块中,因此您将无法在测试中从应用程序访问类。 如何解决这个问题 1.)您可以将应用程序中的类和方法标记为公共,以使其在测试中可见。 2)您可以在单元测试中的任何导入前面添加Swift关键字@testable,以访问该类中导入的所有内容。 @testable导入CoreDataUnitTesting 添加@testable是执行此操作的更好方法,因为您不必将您的类和方法标记为公开以进行测试。 您应用中的核心数据栈将像这样:: 类CoreDataStack { public init(){ } 懒惰的varpersistentContainer:NSPersistentContainer = { 让容器= NSPersistentContainer( 名称:“ CoreDataUnitTesting”) container.loadPersistentStores( completeHandler:{中的(storeDescription,错误) 如果让error = error as NSError? { fatalError(“未解决的错误\(错误), \(error.userInfo)“) } }) 返回容器 }() var applicationDocumentsDirectory:NSURL = { 让urls = FileManager.default.urls(用于: .documentDirectory,位于:.userDomainMask) 返回urls [urls.count-1]作为NSURL }() 公开varmanagedObjectModel:NSManagedObjectModel = […]

管理跨多个分支和计划的应用程序版本的核心数据模型迁移

优点:简单且非常适合具有简单数据模型的小型项目,或者具有很少因发布而变化的数据模型。 对于非常小的项目团队(也可以由一个人来管理所有事情)来说,它也很棒。 缺点:难以管理大型团队或数据模型经常更改或团队规模较大的复杂项目。 如果需要数据模型更新作为热修复程序或在项目的更高分支上,则该更新将必须“波纹化”所有下游分支。 此外,在功能分支上进行更新然后合并回主分支可能会与活动开发中的其他功能冲突。 在整个过程中合并更新可能需要大量的手动工作,并将更新手动合并到许多Core Data模型文件中。 这项工作可能非常令人困惑,难以遵循,并且犯下一个很小的,未引起注意的错误的风险很高,该错误将来会使生产发布应用程序中毒。 选项2)每个发行版本都有其自己的Core Data模型版本文件,因此Beta,Develop和Alpha都具有不同的模型版本说明符。 每个功能分支都共享其父分支的模型,并且不添加模型版本文件。 功能分支仅修改现有模型版本文件。 优点:具有比选项1更大的可伸缩性。一次仅需一次将更改迁移到上游,而在选项1中,可能需要通过几个模型更新文件来使更改产生变化。 数据模型未版本化,可以直接链接到应用程序的特定版本。 更可预测和可理解。 确定数据模型问题以及从错误中恢复要容易得多。 缺点:必须与客户和其他团队成员进行沟通(禁止上空),因为每次更新数据模型时,都必须删除并重新安装开发应用程序以合并新的数据模型。 我在网上找到的所有资源都只提到了如何将核心数据模型从一个版本迁移到另一个版本,这与上面的选项1最相似,但是在过去的几个月中,随着项目的发展,选项1的弊端真正开始了付出代价 从那时起,我发现遵循选项2带来的麻烦最少,并使Core Data模型的git合并非常直接且相对简单。

Xcode 8.1 GM的新增功能

苹果已经发布了Xcode 8.1 GM-这是新版本中的新增功能和改进功能: 快速更新 将C和Objective-C代码导入Swift时,将定义一个新的宏__swift__。 该宏的值的格式为XYYZZ,其中X是语言的主要版本,YY是次要版本 语言的版本,而ZZ是“补丁”版本(YY和ZZ始终为两位数)。 Swift标准库中添加了两种类型:UnsafeRawBufferPointer和UnsafeMutableRawBufferPointer。 它们表示固定内存区域(缓冲区)上的非所有视图。 它们将底层缓冲区公开为UInt8字节的集合,而与该内存中保存的值的类型无关。 一个新的withUnsafeBytes(of :)函数将值的内存表示形式公开为UnsafeRawBufferPointer。 Swift标准数字类型现在作为NSNumber桥接到Objective-C。 NSValue类为其提供工厂方法的结构现在作为NSValue桥接到Objective-C。 由乔·格罗夫(Joe Groff)建议。 当Optional值桥接到Objective-C对象时,当Optional传递给采用非空ID的API或[T?]数组桥接到NSArray时,如果有一个值,Swift运行时将桥接已包装的值。 如果桥接了nil值,并且API不接受nil指针,则Swift将使用NSNull。 由乔·格罗夫(Joe Groff)建议。 快速修复 Swift 3.0.1现在生成一个const UnsafePointer而不是UnsafeMutablePointer。 现在可以正确处理C属性swift_error(zero_result)。 覆盖和满足协议要求的成员的访问检查已修复为与SE-0025更紧密匹配。 如果需要保持Swift 3代码与Xcode 8.0兼容,请对顶级类和结构使用private而不是fileprivate。 解决了使用@NSManaged属性来满足协议要求的问题。 Objective-C更新 现在,使用“手动引用计数”的Objective-C文件支持__weak引用,而不是忽略它。 您需要在项目设置中启用它,否则将触发编译器警告。 核心数据更新 现在,在创建新实体时,Xcode 8将为实体名称和类名称设置相同的值。 更改实体名称也将更改类名称,除非它们已经不同。 核心数据修复 使用自动代码生成保存后,现在可以对数据模型进行更改。 界面生成器更新 新的“更新框架”按钮将更新所选对象及其子对象的框架。 固定按钮已重命名为添加新约束。 自定义手势识别器已添加到对象库,以允许继承UIGestureRecognizer或NSGestureRecognizer而不是使用NSObject。 界面生成器修复 修复了使用重力区域分布的NSStackView的自动布局性能。 解决了布局不明确时Xcode不能始终从情节提要和xib恢复视图帧的几个问题。 现在,您可以解决歧义,并且Xcode将继续存在。 将内容拖动到画布上的静态UITableView单元中,将再次起作用。 创建IBAction连接不再使用Swift 2.3插入WithSender。 在非视网膜上的设备栏中选择横向方向 在OS X 10.11上运行时显示的内容现在将不再挂起。 调试修复 […]

CoreData持久性代码的灵活轻松的单元测试

现代和高质量的iOS应用程序有望完美运行。 确保完美无瑕,耐回归的代码的重要输入是在开发过程中添加全面的单元和集成测试。 本文逐步介绍了使用CoreData作为其持久层为iOS应用程序构建可重复的自动化数据库单元测试的方法。 目标受众 本文假定您了解在iOS应用程序中使用CoreData的基础知识,并且可能已在自己的工作中使用它。 但是,本文的重点是体系结构,即使您不知道如何使用CoreData进行编码,但如果您了解iOS中的数据持久性和单元测试的基础,此处的概念仍然有意义。 代码样例 本文中的代码和概念是使用Xcode 10(测试版)和Swift 4.2开发的。 本文包括用于说明概念的代码摘录,但并未在本文的正文中嵌入此解决方案的所有代码,而是在本文结尾处提供了指向我的GitHub存储库中的示例应用程序的链接。 CoreData是iOS(和macOS)应用程序的默认本地持久性选择。 核心数据从根本上讲是持久化数据存储上的对象关系映射(ORM)层。 虽然CoreData对象的物理存储是从开发人员抽象出来的,但CoreData几乎总是与SQLite一起使用。 如果您是CoreData的新手,或者只是需要复习,那么这里有很多很棒的资源,例如Apple自己的Core Data编程指南和RayWenderlich.com上的Core Data入门指南。 以下是典型应用程序如何访问CoreData的高度简化图。 我将在下面讨论架构的每个元素。 AppDelegate。 该对象表示iOS应用程序的入口点,并且所有iOS开发人员都应该熟悉。 如果使用 Xcode 10中的“ 使用CoreData”选项创建项目,则Xcode将为您创建基本的CoreData堆栈。 在AppDelegate对象中,您会发现以下属性爆炸了。 本质上,此属性是您的应用程序用来访问CoreData管理的数据的挂钩。 类 AppDelegate:UIResponder,UIApplicationDelegate { 。 。 惰性 varpersistentContainer:NSPersistentContainer = {…} 。 。 } NSPersistentContainer属性中具有一个设置,该设置指定是将其数据保存到SQLite磁盘文件(NSSQLiteStoreType) ,内存(NSInMemoryStoreType)还是其他位置(NSBinaryStoreType) 。 后一种情况很少见,在本文中我将不再讨论。 如果未指定任何设置(默认设置), CoreData将使用NSSQLiteStoreType来配置容器。 .xcdatamodel。 当创建具有CoreData支持的项目时,Xcode将自动创建一个数据模型文件 ,其根名称与新项目名称和扩展名xcdatamodel相匹配。 Xcode数据模型编辑器将您不断发展的设计存储在此文件中,并使用此元数据文件为您生成低级CoreData实体模型类。 在Xcode 10中,生成的模型类将自动提供给您的XCTest目标(在某些旧版本的Xcode中不是这种情况,是的!)。 存储管理器。 虽然直接在整个应用程序中访问CoreData和自动生成的实体模型类当然是可能的并且可以接受的,但是将数据操作封装在服务类中是很常见的。 在这种架构中,我已经做到了。 这种方法简化了其余应用程序的数据访问代码,并提供了某种程度的封装,以防基础数据库物理层将来发生变化。 […]

删除核心数据关系规则

要开始处理核心数据的关系,您应该对核心数据框架有所了解。 今天,我将通过适当的示例向您展示删除规则如何与核心数据关系一起工作。 首先设置项目,从xcode创建新项目,名称为Department,如下面的屏幕截图所示。 不要忘记选中使用核心数据复选框。 现在,是时候借助xcode接口创建数据模型了。 打开Department.xcdatamodeld并创建数据模型。 在这里,我将创建两个名称分别为Department和Employee的实体。 部门和雇员实体具有一个类似于名称的属性,更重要的是在这两个实体之间添加关系。 我创建了Department和Employee实体名称之间的一对多关系 ,因为departmentToEmployee因为部门有很多员工。 另外,我还添加了Employee和Department名称之间的To One关系,因为employeeToDepartment因为雇员只有一个部门。 下面的屏幕快照显示了两个实体之间的关系。 删除核心数据规则 现在是时候通过删除一个实体对象来考虑其他实体对象的影响了。 意味着如果员工被删除会怎样? 员工所属的部门是否也应删除? 否。但是,如果删除部门会怎样? 应该有没有部门的员工吗? 在这里图片处理这种情况。 为此,我们在核心数据框架中有删除规则。 每个关系都有删除规则。 删除规则定义删除拥有该关系的对象时发生的情况。 核心数据支持四种基本删除规则。 没有行动 无效化 级联 拒绝 无操作删除规则 如果将删除规则设置为对该关系不执行任何操作 ,则不会发生任何事情。 让我们举个例子,如果部门有很多员工,如果部门被删除,那么员工什么都没有发生。 员工认为其仍与删除的部门有关。 取消删除规则 如果将删除规则设置为对关系无效,则关系的目的地将变为无效。 在我们的情况下,如果部门有很多员工并且部门被删除,部门与员工之间的关系将失效。 这是默认的删除规则,我们经常在项目中使用此规则。 级联删除规则 此删除规则很重要,并且在将规则设置为realtionship时,请确保所有可能的情况。 当数据模型具有更高的依赖性时,通常使用此规则。 在我们的情况下,这意味着,如果部门有很多员工,并且部门被删除,则属于该部门的所有员工都会自动删除。 在使用此规则之前,请确保您的项目要求。 因为如果删除关系对象,此规则将删除所有记录而不会产生任何暗示。 拒绝删除规则 此规则功能强大,与级联规则完全相反。 它可以防止删除记录,而不是按照级联规则删除所有记录。 在我们的情况下,如果部门有很多员工,则仅当删除属于同一部门的所有员工或没有员工与同一部门捆绑在一起时,部门才被删除。 这全部与核心数据的删除规则有关。 在处理两个实体之间的关系之前,请先了解此概念。 在设置删除规则之前,请先了解您的要求。 我希望你们喜欢阅读这个故事。 如果您对此有任何疑问,请与我们联系。

Swift 4.0教程的核心数据

核心数据 -核心数据是用于管理应用程序中的数据模型层对象或实例上下文的框架。 它为与对象生命周期和对象图管理(包括持久性)相关的常见任务提供了通用的自动化数据存储解决方案。 选通启动Goto Xcode并在单个视图上创建New iOS Project。 项目名称CoreDataSwift 在“界面”构建器中单击Main.Storyboard,然后单击项目导航编辑器-嵌入-导航控制器。 然后,单击导航ViewController之后,然后将TableView拖到ViewController中。 使TableView viewcontroller出口代理,数据源并导入CoreData ViewController类:UIViewController,UITableViewDataSource,UITableViewDelegate { 覆盖func viewDidLoad(){ //加载视图后进行其他任何设置,通常是从笔尖进行。 覆盖func didReceiveMemoryWarning(){ super.didReceiveMemoryWarning() //处理所有可以重新创建的资源。 下一个IBOutlet属性TableView UITableView是tableView并注册tableView笔尖viewDidLoad @IBOutlet弱var tableView:UITableView! 覆盖func viewDidLoad(){ tableView.register(UITableViewCell.self,forCellReuseIdentifier:“单元格”) //加载视图后进行其他任何设置,通常是从笔尖进行。 现在我们将选择函数UITableViewDataSource func numberOfSections(在tableView中:UITableView)-> Int { func tableView(_ tableView:UITableView,numberOfRowsInSection部分:Int)-> Int { func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)-> UITableViewCell { 让人=人[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier:“ Cell”,用于:indexPath) cell.textLabel?.text = person.value(forKeyPath:“ name”)as? […]

掌握iOS Swift中的核心数据

核心数据是Apple在macOS和iOS操作系统中提供的对象图和持久性框架。 它允许将由关系实体-属性模型组织的数据序列化为XML,二进制或SQLite存储。 如果您是iOS开发人员,则必须具备有关Core Data的专业知识。 我正在逐步介绍如何使用Core Data创建人名应用程序。 在本教程结束时,您将知道如何: 使用Xcode的模型编辑器来建模数据 将新记录添加到核心数据 从核心数据中获取一组记录 使用表视图显示获取的记录。 在这个项目中,您必须在核心数据中添加一些人名,然后通过获取这些数据,将其显示在tableView中。 专为初学者设计,具有核心数据。 步骤1:建立专案 打开Xcode并基于Single View Application模板创建一个新的iPhone项目。 将应用命名为MyData并确保已选中“使用核心数据” 步骤2:将viewController嵌入导航控制器 步骤3:将tableView添加到Main.Storyboard中的View Controller中 确保将tableView插座正确连接到ViewController类。 步骤4:将栏按钮项目添加到导航栏中 将其命名为“添加名称” 确保已在ViewController类中创建了“ AddName”操作。 第5步:创建一个变量为 var名称:[String] = [] 步骤6:注册tableView单元格 您必须将这些代码放入viewDidLoad中,以使用标识符“ Cell”注册tableView单元。 title =“我的朋友列表” tableView.register(UITableViewCell.self,forCellReuseIdentifier:“ Cell”) 步骤7:创建tableView数据源扩展 将tableView Datasourse扩展名放到ViewController类下面 //标记:– UITableViewDataSource 扩展ViewController:UITableViewDataSource { func tableView(_ tableView:UITableView,numberOfRowsInSection部分:Int)-> Int { 返回names.count } func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)-> […]

Xcode Instruments —僵尸

在保存之前一切都很好。 但是,当我打印获取的结果时,事情发生了。 崩溃…。 这就是我所得到的。 没有控制台日志,没有警告,没有谋杀武器。 最初的线索是EXC_BAD_ACCESS和EXC_1386,表明它的存在,是的,ZOMBIE。 僵尸是保留计数为0的对象仍然继续存在。 要确认它在产品->编辑方案->诊断中启用了僵尸,请为Zombie对象启用复选标记。 再次运行该应用程序,我得到了日志。 由于字符串僵尸对象而导致崩溃的原因。 是时候找到僵尸了。 为了更深入地研究,我们需要侦探“ xcode工具”的帮助。 打开xcode->开发人员工具->工具-> 选择僵尸 在方案中选择所需的模拟器和应用,然后点击红色的录制按钮。 景气,我们弹出这个僵尸, 查看分配历史记录,我发现在获取之后,访问属性“ newName”会导致该属性的内存释放, 但为什么 ? 动机是什么? 过渡到ARC发行说明 描述如何将代码从手动保留/发行转换为使用ARC。 developer.apple.com ARC对方法命名施加了约束: 您不能给访问器一个以new开头的名称。 解决案例后,将核心数据实体的属性从“ newName”重命名为“ updatedName”,解决了崩溃问题。 希望这对您有帮助。 任何帮助都可以通过pratheesh_db@hotmail.com与我联系。