Swift使用CoreData时遇到的一些填坑记录

前言

最近在做一个 App 练手,其中用到了 CoreData 来存储用户的播放列表,由于 CoreData 这部分的文章还是比较少的,所以遇到了不少坑,所以写篇随笔记录一下。

题外话:可以给大家看看这个 App 的界面,我觉得还是挺清新的😄

P.S. 作为背景的氛围图片用的是 CoreImage 生成的

切入正题。

#0 何时执行保存

起初我认为不用显式执行 Xcode 给我们在 AppDelegate 中生成的 saveContext 函数,因为默认情况下 applicationWillTerminate 会执行 saveContext,但是我发现这个生命周期函数压根不靠谱,当用户直接从多任务视图将 App 结束掉时这个函数根本来不及执行完毕,导致我们的数据不能及时写入本地数据库中。所以合理的调用时机我认为还是应该在完成一批操作以后就直接执行一次 saveContext

下面简单贴一下我的部分代码吧:

#1 Relationships 到底什么鬼

另外一个让我很头疼的就是 Relationships,写这块的那天可能有点情绪原因,看苹果官方的 Guideline 看不进去,而且 Google 关于 Relationships 相关的文章也十分少,索性自己闷头研究了。

先说说我遇到了什么问题,我想将属于一个歌单的所有 Song 实体添加到 Playlist 实体的 songs 这个 Relationships 中去,但是发现怎么加都加不进去。我已开始的做法是先用 valueForKey 拿到 songs 属性所代表的 NSManagedObject,然后强制转换到 NSMutableSet 然后执行添加操作,发现人家压根不鸟我这个操作,虽然没有抛异常,也没有任何 log 打出,但是 “It does NOT work!!!”。

经过一番研究,我发现了 NSManagedObject 有个 mutableSetValueForKey,才发现当初我真是傻了逼了....

于是用 mutableSetValueForKey 拿到这个 NSMutableSet 顺利执行添加操作并保存,成功了。

#2 Type Conversion From Objective-C to Swift

这块主要是谈谈一些关于类型的一些事。我们知道 Swift 引入了一系列新的数据类型,比如 String、Int、Dictionary、Array,还有一个神奇的 AnyObject 和 Optional<T> 值。

这里我就直接说了

Swift 中的 String 可以直接作为 NSString 使用,它们之间可以 Toll-Free 转换
Int、Float、Double 仍然不是一个标准的 NSObject 对象,所以 KVC 就没有它们什么事,所以我们仍然需要用 NSNumber 包装一下送入 NSManagedObject,同时拿出来的时候用 xxxValue 取出。

还有,Relationships 一定是 NSSet 类型,不是 NSArray 类型,数据库的关系都是无序的,如果需要有序可以添加一个字段然后查询时用 SortDescription 来排序。

最后,"!"是邪恶符号,慎用。

CoreData在Swift 3.0中的一点改变

在Swift 2.0中我们需要从core data中query结果的时候使用的是如下方式:

func findAnimals() {
let request = NSFetchRequest(entityName:”Animal")
do {
guard let searchResults = try context.executeFetchRequest(request) as? [Animal] else {
print("Results were not of the expected structure")
}
... use(searchResults) ...
} catch {
print("Error ocurred during execution: \(error)")
}
}

注意:以上代码试图将executeFetchRequest返回的结果转换为实际数据类型的数组。同时我们看到,在建立request的时候直接使用的是NSFetchRequest的纯构造器方式。

但是在Swift 3.0中首先我们在创建request的时候必须用范型来指定实际数据类型,你可以用如下任何一句来完成:

let fetch0 = NSFetchRequest<Commit>(entityName: "Commit")

let fetch1:NSFetchRequest<Commit> = Commit.fetchRequest()

接下来在处理fetch结果的时候我们不可以将NSFetchRequestResult直接转换为[Commit],因为这样非相关性的转换总是失败!作为代替我们使用context的另一个方法来完成:

do{
let commits = try managedObjectContext.fetch(fetch)
print("***** \(commits.count) commits *****")
objects = commits
tableView.reloadData()

}catch let error{
print("Fetch failed : \(error.localizedDescription)")
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Swift利用CoreData如何存储多种数据类的通讯录

    前言 我们在上一篇文章简单的实现了一个通讯录,说是通讯录实际上就只是一个简简单单的Name List.这次我们要往这个通讯录里面加入更多的元素,目的也是为了学习CoreData如何存储更多的数据类型.下面话不多说了,来随着小编一起看看详细的介绍吧. 完成后的效果: 1. CoreData支持存储数据类型 咦?这里面有两个好像很少看到的类型:Binary Data.Decimal.Transformable.这些都是神马东西? 1.1 Binary Data 顾名思义,就是二进制数据.对应到OC中

  • Swift利用CoreData实现一个通讯录存储详解

    前言 相信大家对CoreData应该都不陌生,CoreData作为Apple的亲儿子,依然在App需要存储结构化数据上发挥着重要的作用.CoreData已经超过十年了,而且亲爹还在积极的维护着它. Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成数据,也能够将保存在数据库中的数据还原成对象. 虽然其底层也是由类似于SQL的技术来实现,但我们不需要编写任何SQL语句,有点像Java开发中的Hibernate持久化框架 Cor

  • Swift利用CoreData实现一个上班签到的小工具

    前言 我们在之前的两篇里面实现了一个十分简陋的通讯录,而且都是通过系统默认的方式创建的CoreData.可是实际中哪里有那么好的事情嘛,要是忘记在创建工程的时候勾选了下面这个图怎么办? 难道我们要把工程删除,再重新创建嘛?很多时候再开始工程的时候并特么的不知道需要用到数据库啊.更多的时候已经都开始敲代码了,连需求文档都还木有拿到手里,PM只会轻轻的说一句:设计图不是已经有了嘛,先画UI吧. 所以,CoreData Stack是为了解决这个问题诞生的嘛?很遗憾,并不是.看了前面的两篇文章之后,有木

  • Swift使用CoreData时遇到的一些填坑记录

    前言 最近在做一个 App 练手,其中用到了 CoreData 来存储用户的播放列表,由于 CoreData 这部分的文章还是比较少的,所以遇到了不少坑,所以写篇随笔记录一下. 题外话:可以给大家看看这个 App 的界面,我觉得还是挺清新的

  • Flutter iOS开发OC混编Swift动态库和静态库问题填坑

    目录 引言 OC接入Swift 插件 静态库和 Framework 区别 新的问题: non-modular heade 不能在Framework Module中使用非Modular 的 Header 引言 Flutter 在 iOS 上的编译问题相信大家多多少少遇到过,不知道大家在搜索这方便的问题时,得到的答案是不是让你 clean 或者 install 多几次,很多时候就算解决完问题,也是处于薛定谔的状态,所以本篇也简单记录下 Flutter 开发中,OC 混编 Swift 遭遇动态库和静态

  • Android中WebView的基本配置与填坑记录大全

    前言 在应用程序开发过程中,经常会采用webview来展现某些界面,这样就可以不受发布版本控制,实时更新,遇到问题可以快速修复. 但是在Android开发中,由于Android版本分化严重,每一个版本针对webview都有部分更改,因此在开发过程中会遇到各种各样的坑,下面这篇就来给大家介绍关于Android中WebView的基本配置与填坑记录,话不多说了,来一起看看详细的介绍吧. 基本配置 // 硬件加速 getActivity().getWindow().setFlags( WindowMan

  • vscode 安装go第三方扩展包填坑记录的详细教程

    1.vscode中安装go扩展包,不再阐述. 2.在安装好go的扩展包以后,创建GOPATH环境变量 3.PATH中会自动添加,如果没有可手动添加 4.在GOPATH目录下创建自己的工作空间(为什么一定是在GOPATH下创建,还不太清楚),我的是workspace(名称可以自定义) 5.打开VSCODE,文件-打开文件夹,选择GOPATH目录 6.在workspace下创建helloworld目录(我称为项目空间) 7.配置VSCODE中的setting.json文件 加入如下配置: 8.编写h

  • Android ViewPager中显示图片与播放视频的填坑记录

    ViewPager介绍 ViewPager的功能就是可以使视图滑动,就像Lanucher左右滑动那样. ViewPager用于实现多页面的切换效果,该类存在于Google的兼容包android-support-v4.jar里面. ViewPager: 1)ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类. 2)ViewPager类需要一个PagerAdapter适配器类给它提供数据. 3)ViewPager经常和Fragment一起使用,并且

  • Java空集合使用场景与填坑记录

    前言 今天学学Java中如何创建一个空集合以及空集合的一些使用场景和相关的坑.开始之前,我们先来看一下java判断集合是否为空 list.isEmpty() list.size()==0 list==null的区别: 1. isEmpty()方法是用来判断集合中有没有元素 2. size()方法是判断集合中的元素个数 3. isEmpty()和size()==0意思一样,没有区别,通用. 4. if(list ==null)是判断有没有这个集合 在我们判断集合是否为空的时候这样写就万无一失: L

  • golang设置http response响应头与填坑记录

    1. 设置WriteHeader的顺序问题 之前遇到个问题,在一段代码中这样设置WriteHeader,最后在header中取Name时怎么也取不到. w.WriteHeader(201) w.Header().Set("Name", "my name is smallsoup") 用 golang 写 http server 时,可以很方便可通过 w.Header.Set(k, v) 来设置 http response 中 header 的内容.但是需要特别注意的

  • JavaScript代码编写中各种各样的坑和填坑方法

    坑"这个字,在此的意思是"陷阱".由于 JavaScript "弱语言"的性质,使得其在使用过程中异常的宽松灵活,但也极为容易"中招".这些坑往往隐藏着,所以必须擦亮双眼,才能在学习与应用 JS 的道路上走的一帆风顺. 一.全局变量 JavaScript 通过函数管理作用域.在函数内部声明的变量只在这个函数内部,函数外面不可用.另一方面,全局变量就是在任何函数外面声明的或是未声明直接简单使用的. "未声明直接简单使用"

  • Android—基于微信开放平台v3SDK开发(微信支付填坑)

    接触微信支付之前听说过这是一个坑,,,心里已经有了准备...我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是漂亮的,隔着北京的大雾霾我仿佛看见了太阳~~~好了,装逼结束...进入正题 开发准备: 1.在微信开放平台申请账号 2.成功后创建应用,就是填一些看似很官方很正经的资料了...(说审核7天左右,没有意外的情况下你的app第二天就审核成功了是不是很开心,有了appid,是不是就可以调用微   信支付了????-------想多了,真的) 3.微信支付是需要额外

  • 详解centos7上elastic search安装及填坑记

    本文介绍了centos7上elastic search安装及填坑记,分享给大家,具体如下: 下载elastic search 5.3.0 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.3.0.tar.gz mv elasticsearch-5.3.0.tar.gz /opt cd /opt tar -xzvf elasticsearch-5.3.0.tar.gz cd elasticsearch

随机推荐