Swift中第三方Sqlite3框架SQLite.swift使用

在Objective-C中,用于数据持久化的方法有以下几种:

  1. 使用plist文件
  2. 使用preference 保存数据
  3. NSKeyArchiver 归档​
  4. Sqlite3
  5. CoreData

在日常开发中,虽然经常需要储存某些用户的个人信息之类的,这样我们用的更多的是plst和preference,但是对于大批量的数据,比如说TableView中的Data数据进行处理,还是需要数据库来进行处理。

CoreData是基于Sqlite的封装,但是貌似被黑的很惨,这里就暂时不用了。而且因为我自己尝试使用过CoreData,感觉使用的话,不仅仅需要用到图形界面,还要编写代码。对于我这个纯代码党来说,感觉有点复杂。希望苹果公司将来能够对其进行不断改良吧。

而在移动端我们最最常用的还是Sqlite,在OC中,我们有耳熟能详的FMDB,但是在Swift中,我们能使用什么呢?在通过网上搜索了一段时间之后。SQLite.swift映入了我眼帘(我才不会说因为Realm的文档太复杂而不去看他了呢!)

#安装方法

对于使用cocoapods的我来说,第三方库的安装其实相对而言十分简单的。

  1. 只要在该工程下使用vim podfile创建对应的podfile文件
    1. 输入对应的第三方库的名字和版本号:pod 'SQLite.swift', '~> 0.10.1',由于是Swift我们这里还需要换行输入use_frameworks!这样才能将对应的库导入到我们的工程中。
  2. esc后输入:wq,保存文本内容
  3. 输入pod install安装对应库就可以了

如果有小伙伴不知道怎么安装cocoapods,可以参照我的这篇文章来进行安装

#基本介绍

这个第三方框架有着自己详细的官方文档,各位可以点击进去自行查看。不过都是英文的,可能阅读起来有点麻烦。所以我在这简单的介绍下相关的内容。

#基本使用

##创建
对于数据库而言,主要的创建就是数据库的创建和表的创建

###数据库的创建
只要直接获取就可以,这个库会帮我们解决如果文件不存在的问题。

1
let db = try Connection("path/to/db.sqlite3")

###表的创建
首先我们通过库中的Table类来获取这个对象

1
let table = Table("tableName")

然后我们创建我们需要在表中的放入的元素。
这里就需要介绍下
Sqlite中存在的值类型和类中的变量的对应情况了。

Swift Type SQLite Type
Int64 INTEGER
Double REAL
String TEXT
nil NULL
SQLite.Blob BLOB

然后就是创建我们想要的元素对象了
let id = Column(“id”)
let name = Column(“PersonName”)

其中创建的时候中<>中的值就是我们设置的元素,()中的内容就是元素名

在SQLite中的所有涉及到元素的增删改查的所有内容都是使用column对象来进行处理的。

而创建的话也十分简单

1
2
3
4
try db.run(table.create{ t in
t.column(id,primaryKey:true)
t.column(name)
})

当然肯定有人会问很多问题

Q
:表如果已经存在了,那怎么办?元素的唯一性怎么办?主键怎么设置?……

A:别急,听我慢慢道来。

这里框架里面已经给我们提供了很多可以遍历的方法

####解决表已经存在的问题
我们可以翻看他的源代码中的Table类的创建函数create方法,这个创建方法是这么写的

1
func create(temporary temporary: Bool = false, ifNotExists: Bool = false, @noescape block: TableBuilder -> Void) -> String

很明显他里面已经帮我们考虑了我们平常使用中的常用方法,其中temporary就是创建虚拟表(也就是存放在内存中,不存放在实际沙盒路径中的数据表),ifNotExists是判断是否已经存在对应的表文件。block是用来创建对应的TableBuilder对象。

####解决元素的相关属性问题
在create的时候我们使用了闭包,这样就可以在每次执行的时候捕获对象,从而使得每次都能对表进行处理。通过查看他的源码,我们发现这里面的t实际上就是一个TableBuilder对象。我们可以用TableBuilder的column方法

1
func column(name: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?)

当然我们不会直接调用这个方法,毕竟这个方法那么长,不符合Swift编码规范,所以我们可以使用作者已经缩略好的内容,从而方便使用,这里就粗略的介绍下对应变量:

  1. name:对应的Expression类型,也就是我们前面创建的Express<>()的变量
  2. Datetype:元素的类型,就是前面表格中的SwiftType,一般代码会帮我们自动设置好
  3. primaryKey:判断是否要设置为主键
  4. null:是否可以置为null,
  5. unique:是否键值唯一
  6. check:判断对应的内容是否符合某种表解析,比如说:email.check(“%@%”),
  7. reference:添加引用
  8. collate:指定排序规则
  9. defaultValue:默认值

数据的增删改查

###增加

1
try! db.run(users.insert(email <- "alice@mac.com"))

这个返回的是一个Int,即插入对应的行的行id

###删除

1
try db.run(alice.delete())

这个返回的是一个Int,即删除行的数目

那如果需要删除某一行,那就需要使用对应的筛选函数了(在查找中会提到)

###修改

1
try db.run(alice.update(email <- "alice@me.com"))

这个返回的是一个Int,即修改行的数目

###查找
查找和上面的略有不同,因为我们查找,肯定是为了查找某一行的内容,或者说需要对内容进行排列,或者左右连接其他表等等。这个时候我们就需要使用其他的函数了。(因为框架里面没有select方法)

在框架中查找对应的是内容的QueryType的函数主要有这几个filter(筛选),join(表连接),group(group by),limit(对筛选条件进行约束),这几个函数与日常使用的SQL语句使用基本上一致,所以在这不过多解释。但是在使用filter的时候,如果判断值为某个值,那么需要用到column。所以在每次选择前,需要对需要用到的值创建对象。

但是由于选出的值需要进行展示,而且不同人的展示方式不同,比如说有的人要取和,有的人要输出。

除此之外,对于筛选的内容,框架的作者使用链式的方法,从而在编码的过程中更加方便,比如说下面这条语句,很明显让人一读就能力姐他到底是什么意思。

1
2
3
4
let query = users.select(email) // SELECT "email" FROM "users"
.filter(name != nil) // WHERE "name" IS NOT NULL
.order(email.desc, name) // ORDER BY "email" DESC, "name"
.limit(5, offset: 1) // LIMIT 5 OFFSET 1

###数据转换
这个时候单纯的table是不够用了,作者就把方法写到了db里面。

  1. scalar:聚合,用来获得对应想要的值,一般用于获得count,max,min,avg,sum,totle等
  2. prepare:获得所有元素值,然后使用for循环进行遍历(在for循环中,如果想要某个元素的值,你需要使用let idNum = item[id]id为column对象)
  3. pluck:获得一行,如果是选取了所有,那么获得第一行
  4. run:用来执行delete,update,insert,create语句
  5. trace:每次执行sql语句都要执行这里面的内容。(db.trace { print($0) }在执行db的所有方法前,使用这句,会在每次执行的时候都输出sql语句)
  6. excuse:直接执行SQL语句,为了方便写习惯了SQL语句的人。

##删除
删除表可以直接使用drop()方法而删除某一标签,即dropIndex,则调用dropIndex方法。

除此之外,之所以这个框架那么好用,他还重载了符号。比如说你需要写入某个column,你可以使用<-,这大大的方便了代码的可读性,从而提高了理解的效率。