2.12 后端SQL的可见性
如果只在控制台的日志中查看Core Data所输出的结果,那么意义并不算太大。你知不知道这些事情背后究竟发生了什么?Core Data对持久化存储区中的数据到底进行了哪些操作?这些操作是否恰当?为了提供无缝的Core Data体验,系统都生成了哪些SQL查询语句?每次在模拟器中运行程序的时候,是不是会插入重复的对象?
有个极其详尽的调试选项可以提供足够的信息,告诉你这些操作背后所发生的事情,从而令你知道上述那些问题的答案。这个调试选项会把系统自动生成的SQL查询语句打印出来,使开发者深刻认识到Core Data的工作原理。
请按下列步骤修改Grocery Dude,以便开启SQL Debug模式:
1.点击Product>Scheme>Edit Scheme...菜单项。
2.点击Run Grocery Dude,并切换到Arguments分页。
3.点击Arguments Passed On Launch区域中的“+”按钮,以新增参数。
4.输入新参数-com.apple.CoreData.SQLDebug 3,然后点击OK按钮。
现在我们已经开启了第三级(level 3)的SQL Debug模式,然后重新运行应用程序。按下手机的home键(如果是在模拟器中运行,那就按“Shift++H”组合键或点击Hardware>Home菜单项),并观察控制台中的日志。你会看到,系统自动生成了一些INSERT语句,开发者无须手工编写这些语句。图2-7显示了其中一部分输出信息。
图2-7 由Core Data所生成的SQL查询语句
在图2-7中,SQLite bind[0]至SQLite bind[7]等变量都是用来拼合INSERT语句的,而这种INSERT语句的用途则是把托管对象的特性值插入到ZITEM表的行中,这张表位于持久化存储区里。ZITEM表是同Item实体相关联的。通过名称可以看出实体的属性与数据库中的field(字段)是怎样对应起来的。Core Data使用前缀字母“Z”作为其标准的命名约定。
为了验证保存在SQLite持久化存储区里的托管对象,你可能需要借助第三方工具来查看其内容。请注意:笔者并不建议直接修改数据库。图2-8演示了如何寻找包含Grocery-Dude.sqlite文件的iOS仿真器工作目录。由于Library目录是隐藏的,所以需要右击Finder,选择Go to Folder菜单项,然后手工输入目录名。具体的目录位置是:/Users/Username/Library/Application Support/iPhone Simulator/,当然了,你需要把其中的Username部分替换为自己的用户名。Applications目录下面的子目录名称可能会和书中有所不同,因为这是个随机生成的GUID。
图2-8 用iOS仿真器运行Grocery Dude程序之后,其SQLite数据库文件所在的目录
除了Grocery-Dude.sqlite文件以外,在同一目录下还有两个分别以-wal及-shm结尾的文件。iOS 7默认会采用一种新的“数据库日志记录模式”(database journaling mode),而这两个文件正是由这种记录模式所生成的。第8章将会详细讨论这一模式。对于目前来说,为了查看Grocery-Dude.sqlite的内容,我们必须先禁用这种模式。要想禁用iOS 7默认的日志记录模式,就必须在添加持久化存储区的时候传入一种新的选项。
请按下列步骤修改Grocery Dude,以便禁用iOS 7默认的日志记录模式:
1.修改CoreDataHelper.m文件的loadStore方法,把下面这行代码添加到NSError*error=nil这一行之上:
2.在CoreDataHelper.m文件的loadStore方法中找到调用的addPersist-entStoreWithType那行语句,把其中的options:nil换成options:options。
3.再次运行应用程序,然后-wal文件应该就会消失了,这表明所有数据都已存放到Grocery-Dude.sqlite文件里面了。可将-shm文件删除,也可忽略该文件。
通过Google可以搜到很多能够打开SQLite数据库文件的数据库浏览工具。在Sourceforge网站上有一款好工具,名字叫做SQLite Database Browser[1],笔者建议你现在就把它下载下来,并安装在电脑上试试看。由于该程序未经签名认证,所以需要在System Preferences>Security&Privacy>General中开启Allow applications downloaded from Anywhere选项,然后才能使用。如果不想为了使用该程序而开启这个选项,那么可以在Mac App Store中搜索extension:sqlite,这也是一款能够打开.sqlite文件的程序,而且它通过了Mac App Store的认证。
虽说查看数据库的内容对程序调试工作很有帮助,但是对于这种由Core Data所管理的数据库来说,不应该在编写代码时依赖它内部的私有模式,因为苹果公司可能会在不通知开发者的前提下自行改变其结构。
提示 由于Library文件夹是隐藏的,所以若想查看Grocery-Dude.sqlite文件的内容,方便一些的办法是:直接在这个文件上面点击鼠标右键,选择Open With菜单,然后指定用SQLite Database Browser来打开它。请注意,在Xcode中正在运行Grocery Dude程序的时候,不要用数据库浏览工具打开SQLite文件,否则应用程序在尝试打开数据库时会超时。
图2-9演示了持久化存储区中的托管对象所具备的各种特性值。
图2-9 查看Grocery Dude程序持久化存储区中的SQLite数据库文件
假如发现了重复的条目,那就说明上下文保存了不止一次。目前来看,只有当用户按下手机的home键时,程序才会保存上下文。而程序每次启动的时候,demo方法都会插入新对象,于是就产生了重复。但现在不用担心此问题,因为稍后我们就会讲解如何删除托管对象。
请按下列步骤修改Grocery Dude,以免再产生重复的数据:
1.修改AppDelegate.m文件的demo方法,把NSLog以外的所有代码都删掉。
[1] 网址是:http://sourceforge.net/projects/sqlitebrowser/。——译者注