Swift学习教程之SQLite的基础使用

 更新时间:2019年04月16日 11:26:27   作者:godiscoder  
这篇文章主要给大家介绍了关于Swift学习教程之SQLite的基础使用,文中通过示例代码介绍的非常详细,对大家学习或者使用Swift 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)
}

代码说明

  • 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能代替Objective-C吗?

    Swift能代替Objective-C吗?

    这是我在网上上看到的答案,复制粘贴过来和大家分享一下,因为我和很多人一样很关心Swift的出现对Mac开发的影响和对Objective-C的影响。
    2014-09-09
  • Swift data范围截取问题解决方案

    Swift data范围截取问题解决方案

    这篇文章主要介绍了Swift data范围截取问题解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • Swift实现简单计算器项目

    Swift实现简单计算器项目

    这篇文章主要为大家详细介绍了Swift实现简单计算器项目,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • iOS UITableView展开缩放动画实例代码

    iOS UITableView展开缩放动画实例代码

    这篇文章主要介绍了Swift UITableView展开缩放动画实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Swift使用enum抹平数组元素差异实例详解

    Swift使用enum抹平数组元素差异实例详解

    这篇文章主要为大家介绍了Swift使用enum抹平数组元素差异实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Swift使用SnapKit模仿Kingfisher第三方扩展优化

    Swift使用SnapKit模仿Kingfisher第三方扩展优化

    这篇文章主要为大家介绍了Swift SnapKit模仿Kingfisher第三方扩展优化示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Swift中的限定扩展详析

    Swift中的限定扩展详析

    扩展就是向一个已有的类、结构体或枚举类型添加新功能。下面这篇文章主要给大家介绍了关于Swift中限定扩展的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2018-03-03
  • Swift实现堆排序算法的代码示例

    Swift实现堆排序算法的代码示例

    堆排序(HeapSort)是一树形选择排序,堆排序的时间复杂度O(nlogn),这里我们来看一下Swift实现基堆排序算法的代码示例,首先对堆排序算法的基本概念作一个了解:
    2016-06-06
  • Swift中swift中的switch 语句

    Swift中swift中的switch 语句

    本文给大家介绍了swift中的swift语句,以及和c语音中的写法区别,本文介绍的非常详细,需要的朋友参考下
    2016-12-12
  • swift 3.0中实现字符串截取、比较的方法示例

    swift 3.0中实现字符串截取、比较的方法示例

    时,为了使用现有的字符串生成一个新的字符串,我们可以使用截取字符串的方法实现。下面这篇文章主要给大家介绍了关于swift 3.0中实现字符串截取的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴。
    2017-10-10

最新评论