前言
在我们的日常开发中,经常会遇到用户断网或者网络较慢的情况,这样用户在一进入页面的时候会显示空白的页面,那么如何避免没网显示空白页面的尴尬呢?答案就是:先在网络好的时候缓存一部分数据,这样当下次网络情况不好的时候,至少用户可以先看到之前缓存的内容,已达到提高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~
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对小牛知识库的支持。
本文向大家介绍Laravel学习基础之migrate的使用教程,包括了Laravel学习基础之migrate的使用教程的使用技巧和注意事项,需要的朋友参考一下 前言 大家都知道,现在的开发测试都是讲究多人团队协作完成,每个人都有本地环境,在以前我们一般是手动的添加数据,比如在数据库查询器中使用sql语句进行数据插入。如果数据较少,那还是蛮轻松的,但是如果数据过大,那就很蛋疼了,但是这在Larave
本文向大家介绍seajs学习教程之基础篇,包括了seajs学习教程之基础篇的使用技巧和注意事项,需要的朋友参考一下 介绍 众所周知前端开发模块化已经是大势所趋,目前模块化的规范有很多,众所周知的有commonJS,Module/Wrappings和AMD等,而且ES6也着手开始制定模块化机制的实现。类似于c/c++的include,java中的import关键字,在js中也定义了require关键
本文向大家介绍Three.js基础学习教程,包括了Three.js基础学习教程的使用技巧和注意事项,需要的朋友参考一下 一、Three.js官网及使用Three.js必备的三个条件 1.Three.js 官网 https://threejs.org/ 2.使用Three.js必备的三个条件 (To actually be able to display anything with Three.js
本文向大家介绍Django学习笔记之ORM基础教程,包括了Django学习笔记之ORM基础教程的使用技巧和注意事项,需要的朋友参考一下 ORM简介 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据
本文向大家介绍socket.io学习教程之基础介绍(一),包括了socket.io学习教程之基础介绍(一)的使用技巧和注意事项,需要的朋友参考一下 前言 Web端与服务器间的实时数据传输的是一个很重要的需求,但最早只能通过AJAX轮询询实现。在WebSocket标准没有推出之前,AJAX轮询是唯一可行的方式(通过Flash浏览器也可以,但这里不做讨论)。AJAX轮询原理是设置定时器,定时通过AJA
本文向大家介绍Swift 3.0基础学习之闭包,包括了Swift 3.0基础学习之闭包的使用技巧和注意事项,需要的朋友参考一下 前言 闭包是功能性自包含模块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C中的 blocks 以及其他一些编程语言中的 lambdas 比较相似。下面这篇文章就来详细介绍了关于Swift 3.0中的闭包,感兴趣的一起来看看吧。 开始