- 参考书籍:CORE DATA by Tutorials
- 默认有swift基础。
- 默认已阅读上一篇内容。
亲爱的们,上一篇我们简单的讲了Core Data的存储以及读取,我们已经说过了Core Data是对象图形化管理模式,既然对象放在最前面,那么在Core Data中最正确的操作方式应该是使用对象和属性来进行操作。
这一篇的主要内容:
- 使用所有的Attributes的类型。
- 使用对象来进行储存以及读取数据。
- data model的检验限制功能。
(1)、使用所有的Attributes的类型
在这一篇中我们也用一个Demo来演示,Demo如图所示:
那块绿色表示最喜欢的颜色。
那只斯派克表示头像。
(一切从简,以CoreData操作为核心。)
在name和age的输入框输入数据并且选择好日期后,点击Add按钮会将name、年龄、最喜欢的颜色、生日、头像全部保存起来。
点击show按钮会跳转到下一界面,如图:
自行创建一个新的文件并于此界面联系起来,这里不演示如何操作,若有疑问请留言
在这个页面中会显示之前保存的数据。
在上一篇中我们知道在进行Core Data操作之前我们得先建立data model(数据模板),对此有问题的同学请参考[http://www.jianshu.com/p/96e2b321449c]
这是我们建立的数据模型:
Note:你应该发现了在.xcdatamodeld中Attributes(属性)的Type(类型)中有三种整形:Integer 16, Integer 32 和 Integer 64。* 区别就在于占据多大内存,每种类型储存数的大小都有一个范围(当然范围越大的占据内存越多):
Range for 16-bit integer: -32768 to 32767
Range for 32-bit integer: –2147483648 to 2147483647
Range for 64-bit integer: –9223372036854775808 to 9223372036854775807
在实际使用中应该根据需求来确定类型,比如说,在这里年龄使用Integer 16就完全够用。
在Type有一个类型是“Binary Data”,这是一个万能的类型,可以储存一切你能想到的可以翻译成二进制的东西,包括图片、PDF、‘小电影’等等。
但是时间花销和空间花销仿佛是一个悖论,这里也是一样,这种方便的操作方式,牺牲了很大的系统花销。也就是说即使你只是想获取他的名字,但是他也会把整个Binary(二进制)加载到缓存中,而这会十分影响用户体验。
十分幸运,Core Data早就想到这个问题了。选择我们的Binary Data类型的属性在右边的属性栏中你会发现一个名为Allows External Storage的选择框,像这样:
当你勾选了Allows External Storage以后,CoreData将给给每一个值都独立储存,并会生成一个URI作为入口 。
Note:Allows External Storage只有binary data类型拥有,并且,当你勾选了这个选择框以后你就不能使用属性来询问Core Data。
(据说勾选了这个选择框以后还容易导致数据丢失,未验证。)
-
存储非标准类型数据
有一些数据类型在Type一栏中并没有出现,比如UIColor等。
你会如何储存UIColor?像这样(e.g., red: 255, green: 101, blue: 155)?但是,事实上,你可以将UIColor转化为data,然后使用Binary Data类型来进行储存。当你需要读取的时候再将data类型转化为UIColor类型。
Transformable Type
Transformable类型可以储存任何继承自NSCoding的对象,任何你自定义的对象若是继承自NSCoding也可以用Transformable类型来储存。
(2)、使用对象来进行储存以及读取数据
上一篇中我们用key-value来存储、读取数据,look like this:
//Set the name
Test.setValue(name1, forKey: "name")
//Get the name
let name = Test.valueForKey("name")
你的确可以这样操作。但是,这并不意味着你应该这样操作。
key-value并没有充分利用swift类型判断和xcode 自动完成的功能。
最好的方法应该是给每一个Entity创建一个子类,每一个Entity的属性都有自己的类型。
xcode可以自动给Core Data modal中的Entity生成一个类。像这样操作:
选中.xcdatamodeled文件,然后点击Editor->Create NSManagedObject Subclass-> 选中数据模板->选中要生成类的Entity,然后一直点next
在使用我们新创建的对象管理类来进行存醋以及读取等操作之前,我们还有最后一步要做。选择. xcdatamodeled选中Test Entity,打开右边的属性栏,将我们刚才创建的类和Entity连接起来,这看起来似乎和controller和类连接起来有些类似,不过有些不同的就是,这次我们得在类的名字之前添加上ProjectName.。那么在这里就是CoreDataTest2.Test*:
最新的xcode也许会在这一栏自动填写,但经检验出错,所以还是自己重新填一下通过对象管理类来进行存储读取有以下两个好处:
- 充分利用了xcode和编译器。
- 2.你可以重定义已经存在的方法。
有些方法不被允许继承
上一篇我们已经了解过,在进行Core Data操作时第一步就是获取managedContext(‘暂存器’)。上一篇我们通过 application.delegate来获取‘暂存器’,但是这样操作看起来更像是一个全局变量。这一篇我用类与类之间的属性传递的方法,来获取这个‘暂存器’对象,打开AppDelegate.swift
插入以下代码:
<pre><code>
func application(application:UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let viewController = self.window!.rootViewController as ViewController
viewController.managedContext = self.managedObjectContext
return true
}</code></pre>
打开ViewController.swift,添加头文件“import CoreData”,添加一个全局变量。
//这个变量就是我们的‘暂存器’,而这个暂存器在AppDelegate.swift中已经初始化。
var managedContext:NSManagedObjectContext!
给addButton方法添加代码
<pre><code> func insertSampleData() {
//1
let name = self.name.text
let age = self.age.text.toInt()!
let favoriteColor=self.favoriteColor.backgroundColor!
let birthday = self.birthday.date
let avatar = self.Avatar.image!
//2
let entity = NSEntityDescription.entityForName("Test", inManagedObjectContext: managedContext)
let TestObject = Test(entity: entity!, insertIntoManagedObjectContext: managedContext)
//3
TestObject.name=name
TestObject.age=age
TestObject.favoriteColor=favoriteColor
TestObject.birthday=birthday
let avatarData=UIImagePNGRepresentation(avatar)
TestObject.avatar=avatarData
//4
var error: NSError?
if !managedContext.save(&error) {
println("Could not save (error), (error!.userInfo)")
}
</code></pre>
解释一下这一段代码:
- //1 获取在屏幕中输入的各种信息。
- //2 新建一个Test对象TestObject,使用初始化方法
init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) - //3 给新建的TestObject的变量赋值。
- //4 保存‘暂存器’。
是不是使用对象来进行保存方便许多,是的!
现在运行一下app,填写信息(age一栏请填写整数,否则出错,这里只考虑CoreData相关操作),点击add按钮以后信息被储存,点击show按钮以后跳转到下一界面,但是并没有进行任何操作,现在给showViewController添加代码。
读取数据
打开ShowViewController.swift,在viewDidLoad()中添加以下代码。
<pre><code>
override func viewDidLoad() {
super.viewDidLoad()
//1
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let request = NSFetchRequest(entityName:"Test")
var error: NSError? = nil
var results = managedContext.executeFetchRequest(request, error: &error) as! [Test]!
//3
let TestObject=results[results.count-1]
let name = TestObject.name
let age = TestObject.age
let birthday = TestObject.birthday
let favoriteColor:UIColor = TestObject.favoriteColor as! UIColor
let avatar = UIImage(data: TestObject.avatar)
//4
self.Avatar=UIImageView(image: avatar)
self.name.text = name
self.age.text = "(age)"
//格式化输出生日
var fmt=NSDateFormatter()
fmt.dateFormat = "yyyy-MM-dd"
let birthdayString = fmt.stringFromDate(birthday)
self.birthday.text = birthdayString
self.favoriteColor.backgroundColor = favoriteColor
}
</code></pre>
代码解释:
- //1 获取‘暂存器’。
- //2 创建请求,发出请求并将结果转化为Test数组。
- //3 取出数组中最后一个Test,也就是我们在界面上只能显示最后一个输入信息,通过对象的属性我们找到了之前输入的信息。
- //4 将取到的信息显示在界面上,其中favoriteColor从Anyobject转化为UIColor,Avatar从NSData转化为UIImage。
好的,这个Demo基本就完成了,我们来运行一下吧:
别忘了点击Add按钮 成功显示,Demo的确够简陋~~~到了这一篇的最后部分了。
数据验证:
有时候我们对数据的内容有所限制,比如说年龄不能是负的,在coredata中这种验证并不用我们自己来写代码,我们的data model就有这样的功能。
打开我们的data model,选中我们要验证的属性,点开右边的属性辅助栏,如下图所示:
年龄不能小于0,记得打上边上的√在红色框中我们可以限定最大值 和 最小值。
Note:当我们修改我们的data model以后在运行程序会发生错误,原因就是我们修改了我们的model,最简单的解决方法就是把我们的模拟器reset一下。
对data model的任何修改都可能使之发生错误,这个时候不妨把这个按钮按一下
好的,接下来我们监测下当输入超出我们的限定之后发生了什么,还记得我们的保存时的error吗,我们将输入的年龄为-1,我们来看一下输出。
error.userInfo输出了刚才输入的全部信息,包括错误信息既然发生了error,个么问题来了,如何处理error?
<pre><code>
var error: NSError?
if !managedContext.save(&error) {
println("Could not save (error), (error!.userInfo)")
if error!.code == NSValidationNumberTooLargeError{
println("值过大")
}
if error!.code == NSValidationNumberTooLargeError {
println("值过小")
}
}
</code></pre>
if error!.code == NSValidationNumberTooLargeError
if error!.code == NSValidationNumberTooLargeError
这两句判断语句能准确的告诉我们到底是发生了什么错误,根据不同错误以及实际情况来进行处理,灵活机动。
这一篇内容大体就是这样了,主要讲了通过对象来进行存储以及读取,而这样操作的好处就是更加方便,充分利用了swift以及xcode的特性,也不容易出错。
源代码已上传Github:https://github.com/superxlx/CoreDataTest2
好了,在下一篇再见。
网友评论