时间:2021-02-24 09:39:28 | 栏目: | 点击:次
前言
在我们的日常开发中,经常会遇到用户断网或者网络较慢的情况,这样用户在一进入页面的时候会显示空白的页面,那么如何避免没网显示空白页面的尴尬呢?答案就是:先在网络好的时候缓存一部分数据,这样当下次网络情况不好的时候,至少用户可以先看到之前缓存的内容,已达到提高APP的用户体验。
SQLite就是我们实现本地数据缓存的一种方案,SQLite有以下优点:iOS内嵌SQLite;经过时间的验证;开源;跨平台。
OK,废话不多说,现在我们就开始进入SQLite的体验之旅。当然在开始之前我们要做一点准备工作,毕竟我们不打没有准备的仗。
准备工作
创建备用数据
代码如下:
class Goods {
let name: String!
let weight: Int!
var price: Double!
init(name: String, weight: Int, price: Double) {
self.name = name
self.weight = weight
self.price = price
}
}
let goods = Goods(name: "computer", weight: 10, price: 2000.0)
var goodArr = [Goods]()
var dbPath = ""
var db: OpaquePointer?
func createData() {
for index in 0...4 {
let goods = Goods(name: "computer" + "\(index)", weight: index * 10, price: 20.0)
goodArr.append(goods)
}
}
func fetchLibraryPath() {
if let libraryPathString = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first {
let pathURL = URL(fileURLWithPath: libraryPathString).appendingPathComponent("goods.sqlite")
dbPath = pathURL.path
}
}
创建并连接数据库
func openDatabase() -> OpaquePointer? {
var db: OpaquePointer?
if sqlite3_open(dbPath, &db) == SQLITE_OK {
resultLabel.text = "成功打开数据库,路径:\(dbPath)"
return db
} else {
resultLabel.text = "打开数据库失败"
return nil
}
}
通过上面的代码我们可以看到,首先声明了一个OpaquePointer类型的可选值db,接下来调用了sqlite3_open()方法,该方法的作用是:如果之前创建了数据库那么直接打开,若没创建会直接创建一个。如果该方法调用成功,他会返回一个OpaquePointer的值赋值给你传递进去的db。
SQLITE_OK是一个定义在SQLite库中的一个常量,它代表一个Int32的0。SQLite的大多数函数都会返回一个Int32的值,例如SQLITE_ROW (100)、SQLITE_DONE (101)等,详细列表你可以查看这里。
现在你可以通过调用db = openDatabase()来打开或者创建一个数据库了,正常情况下你会看见成功打开数据库,路径:xxx/xxx.sqlite的输出。
现在,我们已经成功的创建了一个名字为goods.sqlite的数据库了,接下来我们要做的就是创建一个表了。
创建表
代码
func createTable() {
let createTableString = """
CREATE TABLE Computer(
Id INT PRIMARY KEY NOT NULL,
Name CHAR(255),
Weight Int,
Price Float);
"""
var createTableStatement: OpaquePointer?
// 第一步
if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {
// 第二步
if sqlite3_step(createTableStatement) == SQLITE_DONE {
resultLabel.text = "成功创建表"
} else {
resultLabel.text = "未成功创建表"
}
} else {
}
//第三步
sqlite3_finalize(createTableStatement)
}
代码说明
首先解释一下createTableString:创建一个名字为Computer的表,Id为主键且不为空,Name不超过255个字符,Weight为Int类型,Price为Float类型。
然后创建了一个OpaquePointer?类型的变量用于下面的函数:sqlite3_prepare_v2()。
插入一条数据
代码
func insertOneData() {
let insertRowString = "INSERT INTO Computer (Id, Name, Weight, Price) VALUES (?, ?, ?, ?);"
var insertStatement: OpaquePointer?
//第一步
if sqlite3_prepare_v2(db, insertRowString, -1, &insertStatement, nil) == SQLITE_OK {
let id: Int32 = 1
//第二步
sqlite3_bind_int(insertStatement, 1, id)
sqlite3_bind_text(insertStatement, 2, goods.name, -1, nil)
sqlite3_bind_int(insertStatement, 3, Int32(goods.weight))
sqlite3_bind_double(insertStatement, 4, goods.price)
//第三步
if sqlite3_step(insertStatement) == SQLITE_DONE {
resultLabel.text = "插入数据成功"
} else {
resultLabel.text = "插入数据失败"
}
} else {
}
//第四步
sqlite3_finalize(insertStatement)
}
代码说明
插入多条数据
代码
func insertMutipleData() {
let insertRowString = "INSERT INTO Computer (Id, Name, Weight, Price) VALUES (?, ?, ?, ?);"
var insertStatement: OpaquePointer?
//第一步
if sqlite3_prepare_v2(db, insertRowString, -1, &insertStatement, nil) == SQLITE_OK {
for (index, good) in goodArr.enumerated() {
let id: Int32 = Int32(index + 1)
//第二步
sqlite3_bind_int(insertStatement, 1, id)
sqlite3_bind_text(insertStatement, 2, good.name, -1, nil)
sqlite3_bind_int(insertStatement, 3, Int32(good.weight))
sqlite3_bind_double(insertStatement, 4, good.price)
//第三步
if sqlite3_step(insertStatement) == SQLITE_DONE {
resultLabel.text = "插入数据成功"
} else {
resultLabel.text = "插入数据失败"
}
//第四步
sqlite3_reset(insertStatement)
}
} else {
}
//第五步
sqlite3_finalize(insertStatement)
}
代码说明
更新数据
代码
func updateData() {
let updateString = "UPDATE Computer SET Name = 'changeComputer' WHERE Id = 2;"
var updateStatement: OpaquePointer?
//第一步
if sqlite3_prepare_v2(db, updateString, -1, &updateStatement, nil) == SQLITE_OK {
//第二步
if sqlite3_step(updateStatement) == SQLITE_DONE {
resultLabel.text = "更新成功"
} else {
}
}
//第三步
sqlite3_finalize(updateStatement)
}
代码说明
删除数据
代码
func deleteData() {
let deleteString = "DELETE FROM Computer WHERE Id = 2;"
var deleteStatement: OpaquePointer?
//第一步
if sqlite3_prepare_v2(db, deleteString, -1, &deleteStatement, nil) == SQLITE_OK {
//第二步
if sqlite3_step(deleteStatement) == SQLITE_DONE {
resultLabel.text = "删除成功"
}
} else {
}
//第三步
sqlite3_finalize(deleteStatement)
}
代码说明
查询一条数据
代码
func queryOneData() {
let queryString = "SELECT * FROM Computer WHERE Id == 2;"
var queryStatement: OpaquePointer?
//第一步
if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK {
//第二步
if sqlite3_step(queryStatement) == SQLITE_ROW {
//第三步
let id = sqlite3_column_int(queryStatement, 0)
let queryResultName = sqlite3_column_text(queryStatement, 1)
let name = String(cString: queryResultName!)
let weight = sqlite3_column_int(queryStatement, 2)
let price = sqlite3_column_double(queryStatement, 3)
resultLabel.text = "id: \(id), name: \(name), weight: \(weight), price: \(price)"
} else {
resultLabel.text = "error"
}
}
//第四步
sqlite3_finalize(queryStatement)
}
代码说明
查询多条数据
代码
func queryAllData() {
let queryString = "SELECT * FROM Computer;"
var queryStatement: OpaquePointer?
//第一步
if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK {
//第二步
while(sqlite3_step(queryStatement) == SQLITE_ROW) {
//第三步
let id = sqlite3_column_int(queryStatement, 0)
let queryResultName = sqlite3_column_text(queryStatement, 1)
let name = String(cString: queryResultName!)
let weight = sqlite3_column_int(queryStatement, 2)
let price = sqlite3_column_double(queryStatement, 3)
resultLabel.text = "id: \(id), name: \(name), weight: \(weight), price: \(price)"
}
}
//第四步
sqlite3_finalize(queryStatement)
}
代码说明
小结
通过上面我们可以总结出执行一个statement的大概流程:sqlite3_prepare_v2():准备,sqlite3_step():执行statement,sqlite3_finalize():结束。好了,到这里SQLite3的增删改查基本操作也就完事了。下一篇我们来了解一下SQLite的进阶用法。Bye~