corea data学习—2
在系列教程一中,我们为对象建立了可视化数据模型,运行了快速肮脏测试并勾在一个表视图(table view)中来显示。而在这个教程,我们将讨论如何把已有的数据导入或者预先载入到Core Data里面,这样我们的应用开始时会有一些好的默认数据。
在系列教程的最后部分,我们将讨论如何使用NSFetchedResultsController来优化应用,降低内存开销和提升响应时间。
Preloading / Importing Existing Data
预载/导入已有数据
我们要如何在Core Data中预先载入数据呢?流行的解决方案有两种:
启动时从外部源填入Core Data。对此,注意到数据库还没有导入,应用可以启动时从外部来源(例如SQLite数据库或是XML文件)读取数据。
在SQLite数据库中预先填充。对此我们可以Core Data在模型基础上建立数据库结构,然后使用工具来填入数据库。这类工具可以是基于Core Data API的Mac或者iPhone应用,或是一些直接填入SQLite数据库的程序。一旦数据库填好了,只需将其包含到应用里面作为默认数据库,在不存在已有的数据库情况下。
我们将会采用第二种方式,因为它更简单更有效。为了填充数据库,我们只需稍微扩展一下已有的Python脚本。
注意到为什么用Python脚本而不是用基于Core Data API的工具来来导入数据,是因为我们现在有点走底层的样子,将来可能会容易损坏…但是对于本教程我认为第一,由于我们刚刚接触了SQLite,这样对学习的经验巩固更好,而且对事情的进展看的更加清楚;第二,更简单!
所以,让我们拿出工程中产生的sqlite数据库的拷贝。找出相关文件的最简单的方法就是在程序委托(application delegate)中persistentStoreCoordinator函数里面storeUrl一行下方设置一个断点。你可以通过检测storeUrl变量的内容来获取sqlite数据库备份文件的完整路径。找到它并拷到你的Python脚本目录。
一旦你找到数据库,使用sqlite3来简单看看数据库的模样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
sqlite3 FailedBanksCD.sqlite
sqlite3> .schema
CREATE TABLE ZFAILEDBANKDETAILS ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER,
Z_OPT INTEGER, ZZIP INTEGER, ZINFO INTEGER, ZUPDATEDDATE TIMESTAMP,
ZCLOSEDATE TIMESTAMP );
CREATE TABLE ZFAILEDBANKINFO ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER,
Z_OPT INTEGER, ZDETAILS INTEGER, ZNAME VARCHAR, ZSTATE VARCHAR,
ZCITY VARCHAR );
CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY,
Z_UUID VARCHAR(255), Z_PLIST BLOB);
CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR,
Z_SUPER INTEGER, Z_MAX INTEGER);
CREATE INDEX ZFAILEDBANKDETAILS_ZINFO_INDEX ON ZFAILEDBANKDETAILS (ZINFO);
CREATE INDEX ZFAILEDBANKINFO_ZDETAILS_INDEX ON ZFAILEDBANKINFO (ZDETAILS);
sqlite> select * from ZFAILEDBANKINFO;
1|2|1|1|Test Bank|Testland|Testville
2|2|1|2|Test Bank|Testland|Testville
3|2|1|3|Test Bank|Testland|Testville
sqlite> select * from ZFAILEDBANKDETAILS;
1|1|1|12345|1|292794835.855615|292794835.679693
2|1|1|12345|2|292794875.943392|292794875.768675
3|1|1|12345|3|292795809.375025|292795809.215297
sqlite> select * from Z_PRIMARYKEY;
1|FailedBankDetails|0|3
2|FailedBankInfo|0|3
这里有段快速描述。Z_METADATA包含了一些关于Core Data需要实现的模型信息。Z_PRIMARYKEY包含了(在其他东西里面)各个实体所用到的最大key。
至于ZFAILEDBANKINFO跟ZFAILEDBANKDETAILS,这些是我们的主要数据表。Z_PK是各个表的唯一id,Z_ENT是他们的实体id(跟Z_PRIMARYKEY表中列出的一样),最后那些是我们的普通字段。
现在让我们写一段Python脚本来填充这个数据库,通过读取老数据库的内容,在新数据库建立相应的行。脚本如下:
import sqlite3; from datetime import datetime, date; import time inConn = sqlite3.connect('banklist.sqlite3') outConn = sqlite3.connect('FailedBanksCD.sqlite') inCursor = inConn.cursor() outCursor = outConn.cursor() outConn.execute("DELETE FROM ZFAILEDBANKINFO") outConn.execute("DELETE FROM ZFAILEDBANKDETAILS") maxId = 0 inCursor.execute("select * from failed_banks") for row in inCursor: closeDate = datetime.strptime(row[5], "%Y-%m-%d %H:%M:%S") updatedDate = datetime.strptime(row[6], "%Y-%m-%d %H:%M:%S") closeDateSecs = time.mktime(closeDate.timetuple()) updatedDateSecs = time.mktime(updatedDate.timetuple()) # Convert time references secs to NSDate reference deltaSecs = time.mktime((2001, 1, 1, 0, 0, 0, 0, 0, 0)) closeDateSecs = closeDateSecs - deltaSecs updatedDateSecs = updatedDateSecs - deltaSecs if row[0] > maxId: maxId = row[0] # Create ZFAILEDBANKINFO entry vals = [] vals.append(row[0]) # Z_PK vals.append(2) # Z_ENT vals.append(1) # Z_OPT vals.append(row[0]) # ZDETAILS vals.append(row[1]) # ZNAME vals.append(row[3]) # ZSTATE vals.append(row[2]) # ZCITY outConn.execute("insert into ZFAILEDBANKINFO values(?, ?, ?, ?, ?, ?, ?)", vals) # Create ZFAILEDBANKDETAILS entry vals = [] vals.append(row[0]) # Z_PK vals.append(1) # Z_ENT vals.append(1) # Z_OPT vals.append(row[4]) # ZZIP vals.append(row[0]) # ZINFO vals.append(closeDateSecs) # ZUPDATEDATE vals.append(updatedDateSecs) # ZCLOSEDATE outConn.execute("insert into ZFAILEDBANKDETAILS values(?, ?, ?, ?, ?, ?, ?)", vals) outConn.execute("update Z_PRIMARYKEY set Z_MAX=?", [maxId]) outConn.commit()
这应该很容易懂,唯一技巧的地方在于转换旧数据库所存文件(字符串)的格式到新的数据库中 (Jeff R.指出NSdate跟Python使用的date格式不同,所以也要转换)
测试一下Python脚本,如果一切顺利,你会看到填充好的数据库:
1
2
3
4
5
6
7
8
9
10
11
12
13
python coreData.py
sqlite3 FailedBanksCD.sqlite
sqlite> select * from ZFAILEDBANKINFO limit 3;
1|2|1|1|Desert Hills Bank|AZ|Phoenix
2|2|1|2|Unity National Bank|GA|Cartersville
3|2|1|3|Key West Bank|FL|Key West
sqlite> select * from ZFAILEDBANKDETAILS limit 3;
1|1|1|57060|1|1269576000|1269576000
2|1|1|34678|2|1269576000|1269576000
3|1|1|34684|3|1269576000|1269576000
一旦你的数据库填入了正确的数据,将数据库文件拖到你的XCode工程Resource文件夹里面。然后打开FailedBanksCDAppDelegate.m,找到persistentStoreCoordinator函数,用下面一行替换掉storeUrl:
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"FailedBanksCD.sqlite"]; NSURL *storeUrl = [NSURL fileURLWithPath:storePath]; // Put down default db if it doesn't already exist NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:storePath]) { NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"FailedBanksCD" ofType:@"sqlite"]; if (defaultStorePath) { [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL]; } }
以上所有工作都是为了确认sqlite文件已经在文档目录里面,并且如果没有(例如应用第一次运行)就会从bundle拷贝包含的数据库。然后Core Data会开始使用预载数据,这样我们就准备好了!从iPhone模拟器目录删除老的SQLITE3文件(或是单击iPhone SimulatorReset Contents and Settings来清除一切),然后重启应用。如果一切顺利,你应该能看到预先填入的银行列表!
下一步要做什么?
此时此刻,我们有了一个跟之前SQLite例子一样有效的明细视图。然而,有了Core Data,只需要再加几个步骤,效率还能提升。因此下个教程我们来讨论如何用NSFetchedResultsController来提升效率!
更多阅读
诺基亚Lumia800真正完美越狱教程 诺基亚lumia800价格
诺基亚Lumia800真正完美越狱教程——简介诺基亚Lumia800的越狱问题固扰大家许久了!先前的方法,例如是否是U盘模式等等,就像是大海捞针一样稀奇。要么是学生帐号,10个软件限制,真正的无锁越狱的做法,是现在最流行的做法,请看我们的现场直播:
山东65所中专办“三二连读” 初中毕业生可报考 山东大学硕博连读
http://www.sina.com.cn 2004/06/13 16:52 青岛晚报晚报讯 记者昨日从省教育厅获悉,今年我省确定65所普通中专举办“三、二连读”高等职业教育。“三、二连读”高职为专科层次,招生对象为应届初中毕业生,学生参加当地初中毕业生升学考
巴拉拉小魔仙观后感 巴啦啦小魔仙观后感
巴拉拉小魔仙是一个讲述魔法的电视剧 ,其中我最喜欢的人就是小蓝姐姐, 小蓝姐姐面带微笑 ,总是关心别人 帮助别人我比较喜欢小蓝姐姐体贴别人 关爱别人的特点。 凌美琪和凌美雪相差的真的是很远很远, 也不能这么说因为人各有各的优点和
转载 新东方四级听力技巧 新东方英语四级技巧
原文地址:新东方四级听力技巧作者:marble四级听力的三个思路:1.学习——基于学生的角度,一定是抱怨学习2.生活——poor,很穷。Student ID 学生证 用于discount 打折,bargain 讨价还价3.学习vs 生活——忙,忙于学习(就是说,解题从这三个思路出
《跟林老师从头开始学习LOGO语言》导读目录
LOGO语言以简单易学、编写程序的概念先进、有利于开发少年儿童的智力而风行于世界。从小学三年级开始到初中一年级是学习LOGO语言的最佳年龄。LOGO语言是国内许多省份小学及部分初中《信息学》课程中必学的内容。参加学习方法:①下