前言

在我们的日常开发中,经常会遇到用户断网或者网络较慢的情况,这样用户在一进入页面的时候会显示空白的页面,那么如何避免没网显示空白页面的尴尬呢?答案就是:先在网络好的时候缓存一部分数据,这样当下次网络情况不好的时候,至少用户可以先看到之前缓存的内容,已达到提高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)

}

代码说明

insertRowString同上。

第四步:调用sqlite3_reset()函数,以便下次循环再次执行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)

}

代码说明

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状态码来结束。

第一步第三步第四步同上。

小结

通过上面我们可以总结出执行一个statement的大概流程:sqlite3_prepare_v2():准备,sqlite3_step():执行statement,sqlite3_finalize():结束。好了,到这里SQLite3的增删改查基本操作也就完事了。下一篇我们来了解一下SQLite的进阶用法。Bye~

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

swift使用mysql教程,Swift学习教程之SQLite的基础使用相关推荐

  1. python使用教程pandas-python学习教程之Numpy和Pandas的使用

    前言 本文主要给大家介绍了关于python中Numpy和Pandas使用的相关资料,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 它们是什么? NumPy是Python语言的一个扩 ...

  2. python networkx教程_Python 学习教程之networkx

    networkx是Python的一个包,用于构建和操作复杂的图结构,提供分析图的算法.图是由顶点.边和可选的属性构成的数据结构,顶点表示数据,边是由两个顶点唯一确定的,表示两个顶点之间的关系.顶点和边 ...

  3. sqlite数据库android使用教程,Android开发教程之 SQLite数据库的使用

    在开发Android应用程序时经常需要存储数据,Android系统提供了SQLite数据库,还提供了SQLiteOpenHelper类,使我们可以很方便的操作数据库.通过一个例子来说明在Android ...

  4. STL快速入门学习教程之map的简单使用

    STL快速入门学习教程之map的简单使用 map是STL中的一个关联容器,它以一对一的数据进行整理(第一个数值称为关键字,且这个关键字只能在map中出现一次,第二个数值称为前关键字的值),正是由于这种 ...

  5. Wireshark数据抓包教程之Wireshark的基础知识

    Wireshark数据抓包教程之Wireshark的基础知识 Wireshark的基础知识 在这个网络信息时代里,计算机安全始终是一个让人揪心的问题,网络安全则有过之而无不及.Wireshark作为国 ...

  6. 菜鸟教程之C语言基础(上)

    菜鸟教程之C语言基础(上) 一.前言: 前几天,在看另一个教程视频,总感觉太啰嗦,讲的东西不符合我想要的. 这里,通过菜鸟教程,看一遍文档,打一遍笔记,想通过这样学一下C语言的基础. 感谢菜鸟教程. ...

  7. anaconda的python使用教程-Python安装教程之Anaconda入门使用总结

    原标题:Python安装教程之Anaconda入门使用总结 如今参加Python培训学习Python开发的小伙伴对Python安装教程比较感兴趣,本篇文章小编就和读者们分享一下Python安装教程之A ...

  8. html+css基础仏学习教程之HTML 中播放声音或者视频的方法有很多种。

    在 HTML 中播放声音或者视频的方法有很多种. HTML 音频 问题,以及解决方法 在 HTML 中播放音频并不容易! 您需要谙熟大量技巧,以确保您的音频文件在所有浏览器中(Internet Exp ...

  9. 写给初学者的深度学习教程之 MNIST 数字识别

    一般而言,MNIST 数据集测试就是机器学习和深度学习当中的"Hello World"工程,几乎是所有的教程都会把它放在最开始的地方.这是因为,这个简单的工程包含了大致的机器学习流程,通过练习这个工程 ...

最新文章

  1. c++ memset 语言_自学C语言不知道从哪儿下手?学习框架都帮你列好了!
  2. [转] Android系统版本号和Android API level对应表
  3. PTA第二个编程题总结
  4. python爬取qq音乐周杰伦_Python爬取20万条评论,告诉你周杰伦为啥弄崩QQ音乐?
  5. 深度学习核心技术精讲100篇(三十八)-滴滴司机调度系统实践
  6. linux 脚本 获取当前目录,Linux下获取脚本当前工作目录的一点感触
  7. 粗虚线和细虚线_建筑图纸的细线,粗线,虚线表示什么
  8. CF986B Petr and Permutations 思维
  9. jquery 回车事件
  10. 让服务器突破性能极限 阿里云神龙论文入选计算机顶会ASPLOS
  11. (数据分析三板斧)第一斧Numpy-第一节:Numpy基本了解
  12. C#LeetCode刷题之#349-两个数组的交集(Intersection of Two Arrays)
  13. C#如何无客户端连接Oracle数据库
  14. javascript页面刷新与定时跳转页面
  15. syntax error near unexpected token `then'
  16. Selenium Grid
  17. 天涯python_用python做了个简易的天涯脱水功能
  18. PENCIL 决策建模器
  19. ArrayList和Linked的区别
  20. MyBatis的高频面试题

热门文章

  1. php数据类型_PHP数据类型能力问题和解答
  2. Java生成随机数的4种方式,以后就用它了!
  3. Redis 面试题补充与汇总
  4. js使用location的方法实验
  5. 华为交换机S3700-TELNET远程管理交换机配置
  6. android 垂直的开关_安卓布局:如何让这两个按钮水平垂直居中
  7. 单片机8×8点阵显示简单汉字的程序_干货 | 浅析单片机制作贪吃蛇游戏
  8. 多个python脚本同时执行_Python实现脚本锁功能(同时只能执行一个脚本)
  9. windows7系统如何设置远程连接
  10. 世界之窗浏览器怎么隐藏收藏栏