内容简介:在我们的日常开发中,经常会遇到用户断网或者网络较慢的情况,这样用户在一进入页面的时候会显示空白的页面,那么如何避免没网显示空白页面的尴尬呢?答案就是:先在网络好的时候缓存一部分数据,这样当下次网络情况不好的时候,至少用户可以先看到之前缓存的内容,已达到提高APP的用户体验。 SQLite就是我们实现本地数据缓存的一种方案,SQLite有以下优点:iOS内嵌SQLite;经过时间的验证;开源;跨平台。 OK,废话不多说,现在我们就开始进入SQLite的体验之旅。当然在开始之前我们要做一点准备工作,毕
在我们的日常开发中,经常会遇到用户断网或者网络较慢的情况,这样用户在一进入页面的时候会显示空白的页面,那么如何避免没网显示空白页面的尴尬呢?答案就是:先在网络好的时候缓存一部分数据,这样当下次网络情况不好的时候,至少用户可以先看到之前缓存的内容,已达到提高APP的用户体验。 SQLite就是我们实现本地数据缓存的一种方案,SQLite有以下优点:iOS内嵌SQLite;经过时间的验证;开源;跨平台。 OK,废话不多说,现在我们就开始进入 SQLite 的体验之旅。当然在开始之前我们要做一点准备工作,毕竟我们不打没有准备的仗。
准备工作
创建备用数据
-
导入SQLite3:
import SQLite3
- 创建一个Goods的类用来表示数据库存储的数据类型
- 创建一个Goods类型的数组
-
声明一个dbPath和db的全局变量,声明一个获取
libraryDirectory
路径的函数( 数据库存放路径如何选择 )
代码如下:
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()
。
-
第一步:该函数会将
createTableString
编译为字节代码(byte code)并返回一个status code,这个函数执行成功则表明database已经准备好了执行任意的SQL statement(就是创建的 SQL 的字符串),该函数执行成功后即会执行sqlite3_step()
。 -
第二步:
sqlite3_step()
用来执行编译完成的statement handle(createTableStatement)并返回一个status code。 -
第三步:在你每一次的操作完成后你必须调用
sqlite3_finalize()
去删除你的statement以避免resource leak。注意:一旦一个statement被finalized,你不应该再一次使用它。
插入一条数据
代码
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) } 复制代码
代码说明
-
insertRowString中的
?
和前面的字段是对应的,它只是占位符的意思,告诉编译器当真正执行该语句的时候会插入相应的值。 -
第二步:
sqlite3_bind_int()
标识你绑定了一个Int类型的值,该函数的第一个参数是你的statement(即insertStatement),第二个参数是?
的位置在你的statement(注意该值是非零的),在此处也就是1,第三个参数为你想绑定的值。sqlite3_bind_text()
函数表示你绑定的是一个text(一般用于比较长的字符串)类型值,该函数比sqlite3_bind_int()
多了额外的两个参数,第四个参数的意思是text的字节数,一般穿-1
,第五个参数是一个closure回调,处理完string后调用。 - 第三步第四步同上
插入多条数据
代码
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) } 复制代码
代码说明
sqlite3_reset()
更新数据
代码
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) } 复制代码
代码说明
-
updateString:将
Id==2
的数据的Name
字段改为changeComputer
。 -
sqlite3_prepare_v2()
:准备,sqlite3_step()
:执行更新statement,sqlite3_finalize()
:结束。
删除数据
代码
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) } 复制代码
代码说明
-
deleteString:删除表中
Id==2
的数据。 -
sqlite3_prepare_v2()
:准备,sqlite3_step()
:执行删除statement,sqlite3_finalize()
:结束。
查询一条数据
代码
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) } 复制代码
代码说明
-
queryString:在
Computer
表中查找所有Id == 2
的数据。 -
第二步:注意此时要判断的status code为
SQLITE_ROW
,如果该判断为true则代表你查询的数据存在在表里。 -
第三步:
sqlite3_column_int()
函数是按照列数取数据,第一个参数是statement,第二个参数则是该字段是第几列(Id 为表里的第一列,从0开始计算)。sqlite3_column_text()
要略微复杂一点,他需要转换类型通过String(cString: queryResultName!)
。 - 第一步、第四步同上
查询多条数据
代码
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) } 复制代码
代码说明
-
第二步:此处为
while
循环,当查询到最后一行时会返回SQLITE_DONE
状态码来结束。 - 第一步第三步第四步同上。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Docker - 入门(一),基础使用
- 一)redis 基础介绍与使用
- Java Properties类使用基础
- golang基础学习-MongoDB使用
- gitlab命令行使用(基础篇)
- 安卓SQLite基础使用指南
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算机程序设计艺术(第3卷 英文版·第2版)
Donald E.Knuth / 人民邮电出版社 / 2010-10 / 119.00元
《计算机程序设计艺术》系列被公认为计算机科学领域的权威之作,深入阐述了程序设计理论,对计算机领域的发展有着极为深远的影响。本书是该系列的第3卷,扩展了第1卷中信息结构的内容,主要讲排序和查找。书中对排序和查找算法进行了详细的介绍,并对各种算法的效率做了大量的分析。 本书适合从事计算机科学、计算数学等各方面工作的人员阅读,也适合高等院校相关专业的师生作为教学参考书,对于想深入理解计算机算法的读......一起来看看 《计算机程序设计艺术(第3卷 英文版·第2版)》 这本书的介绍吧!