Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

iOS-SQLite在项目中实际使用(Swift3)

$
0
0

转载请注明出处:http://blog.csdn.net/qxuewei/article/details/52913622

这里写图片描述

创建数据库管理类SQLiteManager

设置类方法创建单例对象
Swift 中单例对象可以直接输出定义的自身类内的成员变量.

 class SQLiteManager: NSObject {
    //MARK: - 创建类的静态实例变量即为单例对象 let-是线程安全的
    static let instance = SQLiteManager()
    //对外提供创建单例对象的接口
    class func shareInstance() -> SQLiteManager {
        return instance
    }
}

操作数据库

首先需要在项目中导入libsqlite3.tbd框架
这里写图片描述

SQLite3 框架是一套 C 语言的框架,直接在swift中使用首先需要添加桥接文件
在swift中使用OC/C++/C等文件都需要这个桥接文件.
这里写图片描述

创建完桥接头文件还需要将桥接头文件配置到项目中
这里写图片描述

然后就可以在swift项目中愉快的使用C语言的各种接口方法了.

打开数据库

开启数据库

class SQLiteManager: NSObject {
    //MARK: - 创建类的静态实例变量即为单例对象 let-是线程安全的
    static let instance = SQLiteManager()
    //对外提供创建单例对象的接口
    class func shareInstance() -> SQLiteManager {
        return instance
    }
    //MARK: - 数据库操作
    //定义数据库变量
    var db : OpaquePointer? = nil
    //打开数据库
    func openDB() -> Bool {
        //数据库文件路径
        let dicumentPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last
        let DBPath = (dicumentPath! as NSString).appendingPathComponent("appDB.sqlite")
        let cDBPath = DBPath.cString(using: String.Encoding.utf8)
        //打开数据库
        //第一个参数:数据库文件路径  第二个参数:数据库对象
//        sqlite3_open(<#T##filename: UnsafePointer<Int8>!##UnsafePointer<Int8>!#>, <#T##ppDb: UnsafeMutablePointer<OpaquePointer?>!##UnsafeMutablePointer<OpaquePointer?>!#>)
        if sqlite3_open(cDBPath, &db) != SQLITE_OK {
            print("数据库打开失败")
        }
        return creatTable();
    }
    //创建表
    func creatTable() -> Bool {
        //建表的SQL语句
        let creatUserTable = "CREATE TABLE IF NOT EXISTS 't_User' ( 'ID' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,'name' TEXT,'age' INTEGER,'icon' TEXT);"
        let creatCarTable = "CREATE TABLE IF NOT EXISTS 't_Car' ('ID' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,'type' TEXT,'output' REAL,'master' TEXT);"
        //执行SQL语句-创建表 依然,项目中一般不会只有一个表
        return creatTableExecSQL(SQL_ARR: [creatUserTable,creatCarTable])
    }
    //执行建表SQL语句
    func creatTableExecSQL(SQL_ARR : [String]) -> Bool {
        for item in SQL_ARR {
            if execSQL(SQL: item) == false {
                return false
            }
        }
        return true
    }
    //执行SQL语句
    func execSQL(SQL : String) -> Bool {
        // 1.将sql语句转成c语言字符串
        let cSQL = SQL.cString(using: String.Encoding.utf8)
        //错误信息
        let errmsg : UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>? = nil
        if sqlite3_exec(db, cSQL, nil, nil, errmsg) == SQLITE_OK {
            return true
        }else{
            print("SQL 语句执行出错 -> 错误信息: 一般是SQL语句写错了 \(errmsg)")
            return false
        }
    }
}

一般在app启动开启数据库并建表

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        //一般在程序启动时开始数据库并建表
        if SQLiteManager.shareInstance().openDB() {
            print("开启数据库成功!")
        }
        return true
    }

数据库内SQL操作

//执行SQL语句
    func execSQL(SQL : String) -> Bool {
        // 1.将sql语句转成c语言字符串
        let cSQL = SQL.cString(using: String.Encoding.utf8)
        //错误信息
        let errmsg : UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>? = nil
        if sqlite3_exec(db, cSQL, nil, nil, errmsg) == SQLITE_OK {
            return true
        }else{
            print("SQL 语句执行出错 -> 错误信息: 一般是SQL语句写错了 \(errmsg)")
            return false
        }
    }

项目中的Model自定义对象可以自定义一个将自身插入数据库的方法

//将自身插入数据库接口
    func insertSelfToDB() -> Bool {
        //插入SQL语句
        let insertSQL = "INSERT INTO 't_User' (name,age,icon) VALUES ('\(name!)',\(age),'\(icon!)');"
        if SQLiteManager.shareInstance().execSQL(SQL: insertSQL) {
            print("插入数据成功")
            return true
        }else{
            return false
        }
    }

模拟插入若干用户

for i in 1...7 {
            let name = "name_\(i)"
            let age = arc4random_uniform(18).hashValue + i
            let icon = "http://qiuxuewei.com/icon\(i).png"
            let user : User = User(name: name, age: age, icon: icon)
            if user.insertSelfToDB() {
                print("第 \(i) 个用户插入成功!")
            }
        }
    }

如果需要更新数据库对应表中数据,直接调用SQL执行方法即可实现

//修改头像封装方法
func changeIcon(newIcon : String) {
        //包装修改头像的SQL语句
        let changeIconSQL = "UPDATE 't_User' SET icon='\(newIcon)' WHERE name='name_6'"
        if SQLiteManager.shareInstance().execSQL(SQL: changeIconSQL) {
            print("name_6 头像修改成功!")
        }
    }

查询数据库中对应表中所有数据

在SQLiteManager中封装一个类方法,可以直接传入SQL语句输出数据库中存储的数据
其中swift3中对 UnsafePointer 转 String 做了改动
let s = String(cString: yourCharPointer)
参考:http://stackoverflow.com/questions/39533320/swift-3-convert-a-null-terminated-unsafepointeruint8-to-a-string

//查询数据库中数据
    func queryDBData(querySQL : String) -> [[String : AnyObject]]? {
        //定义游标对象
        var stmt : OpaquePointer? = nil

        //将需要查询的SQL语句转化为C语言
        if querySQL.lengthOfBytes(using: String.Encoding.utf8) > 0 {
            let cQuerySQL = (querySQL.cString(using: String.Encoding.utf8))!
            //进行查询前准备操作
            // 1> 参数一:数据库对象
            // 2> 参数二:查询语句
            // 3> 参数三:查询语句的长度:-1
            // 4> 参数四:句柄(游标对象)

            if sqlite3_prepare_v2(db, cQuerySQL, -1, &stmt, nil) == SQLITE_OK {
                //准备好之后进行解析
                var queryDataArrM = [[String : AnyObject]]()
                while sqlite3_step(stmt) == SQLITE_ROW {
                    //1.获取 解析到的列(字段个数)
                    let columnCount = sqlite3_column_count(stmt)
                    //2.遍历某行数据
                    var dict = [String : AnyObject]()
                    for i in 0..<columnCount {
                        // 取出i位置列的字段名,作为字典的键key
                        let cKey = sqlite3_column_name(stmt, i)
                        let key : String = String(validatingUTF8: cKey!)!

                        //取出i位置存储的值,作为字典的值value
                        let cValue = sqlite3_column_text(stmt, i)
                        let value =  String(cString:cValue!)
                        dict[key] = value as AnyObject
                    }
                    queryDataArrM.append(dict)
                }
                return queryDataArrM
            }
        }
        return nil
    }

在自定义模型中有必要定义个工厂方法可将数据库对应表中所有数据取出,以模型数组的形式输出

 //MARK: - 类方法
    //将本对象在数据库内所有数据全部输出
    class func allUserFromDB() -> [User]? {
        let querySQL = "SELECT name,age,icon FROM 't_User'"
        //取出数据库中用户表所有数据
        let allUserDictArr = SQLiteManager.shareInstance().queryDBData(querySQL: querySQL)
        print(allUserDictArr)

        //将字典数组转化为模型数组
        if let tempUserDictM = allUserDictArr {
            // 判断数组如果有值,则遍历,并且转成模型对象,放入另外一个数组中
            var userModelArrM = [User]()
            for dict in tempUserDictM {
                userModelArrM.append(User(dict: dict))
            }
            return userModelArrM
        }
        return nil
    }

当然,github已经上传源代码:https://github.com/qxuewei/Swift-test/tree/master/SQLite%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C-Swift

作者:qiuxuewei2012 发表于2016/10/25 14:50:21 原文链接
阅读:88 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>