本人有若干成套學習視頻, 可試看! 可試看! 可試看, 重要的事情說三遍 包含Java, 數據結構與算法, iOS, 安卓, python, flutter等等, 如有需要, 聯系微信tsaievan.
SQLite = SQL + Lite(light)
SQL = Structured Query Language (結構化查詢語言)
SQLite 是一款輕型的數據庫, 具有以下特點:
- 嵌入式的
- 占用資源少, 運行速度快
- Mac 已經內置了 SQLite
關系型數據庫的特點
- 一個字段(field/col)存儲一個值,類似于存儲的一個屬性
- 一行(row)存儲一條記錄,類似于一個對象
- 一個表(table)存儲一系列數據,類似于一個對象數組
- 多個表之間存在一定的關系,類似于對象之間的關系
相關術語
-
字段(field/col),一個字段存儲一個值,可以存儲 INTEGER ,REAL ,TEXT ,BLOB,NULL 等五種類型的數據
- SQLite 存儲在本質上并不區(qū)分數據類型
主鍵(primary key)
- 自動增長,程序員不需要關心
- 外鍵(foreign key)
- 通過外鍵對應起和其他"表(table)"的關系
開發(fā)數據庫的步驟(關鍵)
- 建立數據庫 ->有存儲數據的文件
- 創(chuàng)建表->每一張數據表存儲一類數據
- 利用 SQL 語句對其進行增刪查改,并在 UI 中顯示
移動應用中使用數據庫的好處
實際上,隨著 4G 網絡的普及以及數據的更新數據加快,這一優(yōu)勢正在慢慢削弱
- 將網絡數據存儲在本地,不用每次網絡下載,節(jié)省用戶流量
- 對本地數據進行查詢
使用第三方框架 FMDB 來操作 SQLite 數據庫的 Demo
iOS原生的操作數據庫的方法十分繁瑣, 所以一般使用第三方框架來操作SQLite 數據庫.
總體思路導圖

總體思路導圖
在使用的過程中,需要用到一些常用的 SQL 語句,這些語句對于一些非專業(yè)的開發(fā)人員來說,不需要去記憶,我們只需要安裝 navicat 這個軟件,然后會自動生成一些常用的 SQL 命令,我們將其 copy 下來供日后使用
下文即是 demo 的主要步驟
- 在 pod 中導入 FMDB
- 在target 中添加FMDatabaseAdditionsVariadic和FMDatabaseVariadic兩個 swift 文件
先介紹一下 FMDBDatabase 類
我們首先要創(chuàng)建一個中間管理層對 FMDBDatabase 類進行一個封裝
這個中間管理層就叫做 FMDBManager
FMDBManager中的代碼
import UIKit
/* 導入 FMDB 框架 (不同的命名空間)*/
import FMDB
class FMDBManager: NSObject {
//--------- 首先創(chuàng)建一個單例(管理工具類) ---------
static let sharerdManager = FMDBManager()
var db: FMDatabase?
//--------- 創(chuàng)建數據庫 ---------
func openDB() {
/* 首先給出一個路徑 */
/* NSSearchPathForDirectoriesInDomains返回的是一個數組,所以要取出最后一個元素才能獲得路徑,否則無法拼接出正確的地址,那么在獲取路徑的時候就獲取不到,造成無法創(chuàng)建數據庫文件 */
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last!
/* 打印出存儲路徑,供查詢使用 */
print(path)
/* 給數據庫起一個名字 */
let databaseName = "testSqlite.sqlite"
/* 將數庫的名字拼接在路徑后面 */
let databasePath = "\(path)/\(databaseName)"
//--------- 初始化 db ---------
db = FMDatabase(path: databasePath)
if db!.open() {
print("數據連接成功")
//--------- 創(chuàng)建一個表 ---------
creatTable()
}else{
print("數據連接失敗")
}
}
//--------- 關于FMDBDatabase的使用 ---------
/* 1. 創(chuàng)建,增刪改 均使用 executeUpdate*/
/* 2. 查詢使用 executeQuery方法*/
func creatTable() {
//--------- 執(zhí)行 sql 語句(不需要記憶)創(chuàng)建一個表格 ---------
let sql = "CREATE TABLE IF NOT EXISTS t_emotion ('id' integer NOT NULL,'png' text NOT NULL,'text' text NOT NULL,PRIMARY KEY('id'))"
// func executeUpdate(sql:String, _ values: AnyObject...) throws
/* 當看到方法中出現 throws 時,必須做異常處理,否則報錯 */
try! db?.executeUpdate(sql, [])
}
}
- 我們將對數據庫進行增,刪,改的操作都交給 模型來處理
假定一個應用場景是將所有的表情(例如emoji表情)都存儲在數據庫中,那么我就可以將每一個表情都看作是一個模型,將模型存儲在數據庫中,先創(chuàng)建一個模型類 EmotionModel 類
EmotionModel 類中的代碼:
import UIKit
class EmotionModel: NSObject {
/* 圖片 */
var png:String?
/* 名稱 */
var text:String?
/* kvc 構造函數 */
init(dict:[String:AnyObject]) {
super.init()
setValuesForKeysWithDictionary(dict)
}
/* 異常處理 */
override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
}
// MARK:- 對數據庫進行相關的操作
extension EmotionModel {
/* 添加數據 */
func insert () {
/* 執(zhí)行添加數據的 sql 語句 */
let sql = "INSERT INTO 't_emotion' ('png', 'text') values ('\(self.png!)', '\(self.text!)')"
try! FMDBManager.sharerdManager.db?.executeUpdate(sql, [])
}
}
- 這樣, 在控制器中,假如我要添加模型 就只需要將 plist 文件中,或者網絡加載出的 JSON 數據,字典轉模型,再調用模型的對象方法,將模型對象存儲到數據庫中即可,控制器中的代碼如下:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// insertData()
queryData()
}
}
// MARK:- 操作數據,更新 UI
//--------- 在控制器中我們只管理 UI 的相關操作,從數據庫中獲取數據我們交給模型來操作 ---------
/* 比如我們想在數據庫的表中添加數據,就直接交給模型來做 */
extension ViewController {
/* 先創(chuàng)建100個模型,放到數據庫的表中 */
func insertData() {
for i in 0..<100 {
let dict = ["png":"\(i).png", "text":"測試\(i)"]
let emotionModel = EmotionModel(dict: dict)
emotionModel.insert()
}
}
}
- 如果我需要查詢數據,就需要使用到另外一個方法: executeQuery,這個方法是有返回值的,返回值是一個 FMResultSet 對象,假設我們現在有一個應用場景是將數據庫中的所有數據打印出來,那么我們就在模型類中提供一個類方法,供外界調用
EmotionModel 類中的補充代碼
class func query ()->[[String : AnyObject]] {
/* 該 sql 語句是選中表中的某一個 row */
let sql = "SELECT * FROM t_emotion"
/* executeQuery方法的返回值是一個FMResultSet類型的數據 */
/* 創(chuàng)建一個可變的數組,數組里面的元素是字典 */
var dataArray : [[String : AnyObject]] = []
if let result = try! FMDBManager.sharerdManager.db?.executeQuery(sql, []) {
while result.next() {
let png = result.stringForColumn("png")
let text = result.stringForColumn("text")
let dict = ["png":png, "text":text]
dataArray.append(dict)
}
}
return dataArray
}
- 此時我們在控制器中調用的時候就可以直接調用模型類方法的 API,代碼如下:
func queryData () {
let dataArray = EmotionModel.query()
print(dataArray)
}
再介紹一下 FMDBDatabaseQueue 類
考慮到線程安全問題, 推薦使用 FMDBDatabaseQueue類,其實FMDBDatabaseQueue和 FMDBDatabase 類基本一樣,只是多了一個閉包,將我們要執(zhí)行的數據庫操作放到閉包里去實現
同樣需要創(chuàng)建一個中間層的管理類,叫做 FMDBQueueManager 類
代碼如下
import UIKit
import FMDB
class FMDBQueueManager: NSObject {
//--------- 同樣 ,我們先創(chuàng)建一個管理類的單例 ---------
static let sharedQueueManager = FMDBQueueManager()
//--------- 我們?yōu)檫@個管理類設置一個屬性,是 FMDBDatabaseQueue 類 ---------
var dbQueue : FMDatabaseQueue?
//--------- 創(chuàng)建并打開數據庫的方法 ---------
func openDB () {
/* 首先給出一個路徑 */
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last!
/* 將路徑打印出來供調試使用 */
print(path)
/* 給數據庫起一個名字 */
let databaseName = "sqliteTestTwo.sqlite"
/* 拼接路徑 */
let databasePath = "\(path)/\(databaseName)"
/* 初始化 dbQueue */
dbQueue = FMDatabaseQueue(path: databasePath)
/* 創(chuàng)建一個表 */
creatTable ()
}
}
extension FMDBQueueManager {
func creatTable () {
/* 給出一個創(chuàng)建表的 sql 語句 */
let sql = "CREATE TABLE IF NOT EXISTS t_emotion ('id' integer NOT NULL,'png' text NOT NULL,'text' text NOT NULL,PRIMARY KEY('id'))"
/* 將執(zhí)行 sql 語句的操作放到閉包中去執(zhí)行 */
dbQueue?.inDatabase({ (FMDatabase) in
/* 一定要注意,這里是使用 executeUpdate,而不是 executeQuery */
try! FMDatabase.executeUpdate(sql, [])
})
}
}
- 那么在模型類中的添加數據的代碼也將改變,EmotionModel 中的代碼如下
/* 添加數據 */
func insert () {
/* 執(zhí)行添加數據的 sql 語句 */
let sql = "INSERT INTO 't_emotion' ('png', 'text') values ('\(self.png!)', '\(self.text!)')"
FMDBQueueManager.sharedQueueManager.dbQueue?.inDatabase({ (FMDatabase) in
try! FMDatabase.executeUpdate(sql, [])
})
}
- 控制器中的代碼完全不需要變化
- 在模型類中,查詢數據庫的代碼也需要作出改變,代碼如下:
class func query ()->[[String : AnyObject]] {
/* 該 sql 語句是選中表中的某一個 row */
let sql = "SELECT * FROM t_emotion"
/* executeQuery方法的返回值是一個FMResultSet類型的數據 */
/* 創(chuàng)建一個可變的數組,數組里面的元素是字典 */
var dataArray : [[String : AnyObject]] = []
FMDBQueueManager.sharedQueueManager.dbQueue?.inDatabase({ (FMDatabase) in
if let result = try! FMDatabase?.executeQuery(sql, []) {
while result.next() {
let png = result.stringForColumn("png")
let text = result.stringForColumn("text")
let dict = ["png":png, "text":text]
dataArray.append(dict)
}
}
})
return dataArray
}
運行結果如下

運行結果