第十二篇、Swift_Sqlite的使用

   2023-02-08 学习力0
核心提示: import UIKitclass SQLiteManager: NSObject {private static let manager: SQLiteManager = SQLiteManager()/// 单粒class func shareManager() -SQLiteManager {return manager}// 数据库对象private var db:COpaquePointer = nil// 创建一个串行队列priv

 

import UIKit

class SQLiteManager: NSObject {

    private static let manager: SQLiteManager = SQLiteManager()
    /// 单粒
    class func shareManager() ->SQLiteManager {
        return manager
    }
    
    // 数据库对象
    private var db:COpaquePointer = nil
    
    // 创建一个串行队列
    private let dbQueue = dispatch_queue_create("com.520it.lnj", DISPATCH_QUEUE_SERIAL)
    
    func execQueueSQL(action: (manager: SQLiteManager)->())
    {
        // 1.开启一个子线程
        dispatch_async(dbQueue) { () -> Void in
            print(NSThread.currentThread())
            // 2.执行闭包
            action(manager: self)
        }
    }
    
    /**
    打开数据库
    
    :param: SQLiteName 数据库名称
    */
    func openDB(SQLiteName: String)
    {
        // 0.拿到数据库的路径
        let path = SQLiteName.docDir()
        print(path)
        let cPath = path.cStringUsingEncoding(NSUTF8StringEncoding)!
        // 1.打开数据库
        /*
        1.需要打开的数据库文件的路径, C语言字符串
        2.打开之后的数据库对象 (指针), 以后所有的数据库操作, 都必须要拿到这个指针才能进行相关操作
        */
        // open方法特点: 如果指定路径对应的数据库文件已经存在, 就会直接打开
        //              如果指定路径对应的数据库文件不存在, 就会创建一个新的
        if sqlite3_open(cPath, &db) != SQLITE_OK
        {
            print("打开数据库失败")
            return
        }
        
        // 2.创建表
        if creatTable()
        {
            print("创建表成功")
        }else
        {
            print("创建表失败")
        }
    }
    
    private func creatTable() -> Bool
    {
        // 1.编写SQL语句
        // 建议: 在开发中编写SQL语句, 如果语句过长, 不要写在一行
        // 开发技巧: 在做数据库开发时, 如果遇到错误, 可以先将SQL打印出来, 拷贝到PC工具中验证之后再进行调试
        let sql = "CREATE TABLE IF NOT EXISTS T_Person( \n" +
        "id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
        "name TEXT, \n" +
        "age INTEGER \n" +
        "); \n"
//        print(sql)
        // 2.执行SQL语句
        return execSQL(sql)
    }
    
    /**
    执行除查询以外的SQL语句
    
    :param: sql 需要执行的SQL语句
    
    :returns: 是否执行成功 true执行成功 false执行失败
    */
    func execSQL(sql: String) -> Bool
    {
        // 0.将Swift字符串转换为C语言字符串
        let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!
        
        // 在SQLite3中, 除了查询意外(创建/删除/新增/更新)都使用同一个函数
        /*
        1. 已经打开的数据库对象
        2. 需要执行的SQL语句, C语言字符串
        3. 执行SQL语句之后的回调, 一般传nil
        4. 是第三个参数的第一个参数, 一般传nil
        5. 错误信息, 一般传nil
        */
        if sqlite3_exec(db, cSQL, nil, nil, nil) != SQLITE_OK
        {
            return false
        }
        return true
    }
    
    /**
    查询所有的数据
    :returns: 查询到的字典数组
    */
    func execRecordSQL(sql: String) ->[[String: AnyObject]]
    {
        // 0.将Swift字符串转换为C语言字符串
        let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!
        
        // 1.准备数据
        // 准备: 理解为预编译SQL语句, 检测里面是否有错误等等, 它可以提供性能
        /*
        1.已经开打的数据库对象
        2.需要执行的SQL语句
        3.需要执行的SQL语句的长度, 传入-1系统自动计算
        4.预编译之后的句柄, 已经要想取出数据, 就需要这个句柄
        5. 一般传nil
        */
        var stmt: COpaquePointer = nil
        if sqlite3_prepare_v2(db, cSQL, -1, &stmt, nil) != SQLITE_OK
        {
            print("准备失败")
        }
        
        // 准备成功
        var records = [[String: AnyObject]]()
        
        // 2.查询数据
        // sqlite3_step代表取出一条数据, 如果取到了数据就会返回SQLITE_ROW
        while sqlite3_step(stmt) == SQLITE_ROW
        {
            // 获取一条记录的数据
            let record = recordWithStmt(stmt)
            // 将当前获取到的这一条记录添加到数组中
            records.append(record)
        }
        
        // 返回查询到的数据
        return records
    }
    
    /**
    获取一条记录的值
    
    :param: stmt 预编译好的SQL语句
    
    :returns: 字典
    */
    private func recordWithStmt(stmt: COpaquePointer) ->[String: AnyObject]
    {
        // 2.1拿到当前这条数据所有的列
        let count = sqlite3_column_count(stmt)
        //            print(count)
        // 定义字典存储查询到的数据
        var record  = [String: AnyObject]()
        
        for index in 0..<count
        {
            // 2.2拿到每一列的名称
            let cName = sqlite3_column_name(stmt, index)
            let name = String(CString: cName, encoding: NSUTF8StringEncoding)!
            //                print(name)
            // 2.3拿到每一列的类型 SQLITE_INTEGER
            let type = sqlite3_column_type(stmt, index)
//                print("name = \(name) , type = \(type)")
            
            switch type
            {
            case SQLITE_INTEGER:
                // 整形
                let num = sqlite3_column_int64(stmt, index)
                record[name] = Int(num)
            case SQLITE_FLOAT:
                // 浮点型
                let double = sqlite3_column_double(stmt, index)
                record[name] = Double(double)
            case SQLITE3_TEXT:
                // 文本类型
                let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt, index))
                let text = NSString(CString: cText, encoding: NSUTF8StringEncoding)!
                record[name] = text
            case SQLITE_NULL:
                // 空类型
                record[name] = NSNull()
            default:
                // 二进制类型 SQLITE_BLOB
                // 一般情况下, 不会往数据库中存储二进制数据
                print("")
            }
        }
        return record
    }
    
}

 

使用事务插入数据:

       let manager = SQLiteManager.shareManager()
        
        // 开启事务
        manager.beginTransaction()
        
        for i in 0..<10000
        {
            let p = Person(dict: ["name": "zs + \(i)", "age": 3 + i])
            p.insertPerson()
            
            if i == 1000
            {
                manager.rollbackTransaction()
                // 注意点: 回滚之后一定要跳出循环停止更新
                break
            }
        }
        
        // 提交事务
        manager.commitTransaction()

 

预编译绑定:

    //1、打开数据库  
    sqlite3 *db = [self sqlite3_open_database];  
    //2、建立预编译语句对象并编译  
    charchar *sql = "INSERT INTO student(name,age) VALUES(?,?)";//?为占位符,代表此处将来用变量值替换  
    //2.1、准备预编译语句对象  
    sqlite3_stmt *stmt = NULL;  
    //2.2、预编译sql语句  
    int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);  
    //2.3、预编译成功,绑定值  
    if (result == SQLITE_OK) {  
        //绑定界面数据到预编译sql语句中  
        sqlite3_bind_text(stmt, 1, [self.txtName.text UTF8String], -1, NULL);  
        sqlite3_bind_int(stmt, 2, [self.txtAge.text intValue]);  
        //3、执行预编译语句对象,4、使用结果  
        result = sqlite3_step(stmt);  
        if (result == SQLITE_DONE) {  
            [self myAlert:@"插入数据成功!"];  
        } else {  
            [self myAlert:@"插入数据失败!"];  
        }  
    }  
    //5、销毁预编译语句对象,关闭数据库  
    sqlite3_finalize(stmt);  
    sqlite3_close(db); 

 

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • swift 命令行工具初探
    亲爱的同学们好,今天我们要介绍这么一个东西。相信有过解释型语言(PHP,Ruby,等)使用经验的同学会更加熟悉,就是 Swift 也为我们提供了命令行运行工具,俗称 REPL。好了,我们进入正题,在安装好 Swift 开发环境的机器上,打开命令行,输入 swift 命令,就进
    03-16
  • [Swift]冒泡排序 | Bubble sort
    [Swift]冒泡排序 | Bubble sort
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)➤GitHub地址:https://github.com/strengthen/LeetCode➤原文
    03-08
  • [Swift] 自定义在 SwiftUI 中实现的可搜索的外观
    [Swift] 自定义在 SwiftUI 中实现的可搜索的外
    首先我找遍了,似乎找不到任何信息......(我遇到了许多根本不起作用的事情......)终于在详细的英文文献中找到了,我会保留下来,希望以后有机会。关于 SwiftUI 中的可搜索searchable是iOS15新增的易于实现的搜索字段。关于这种情况有一个参数placement,您
    03-08
  • [Swift] 检测 SwiftUI ScrollView 中的偏移量
    [Swift] 检测 SwiftUI ScrollView 中的偏移量
    首先你可以用ScrollViewReader做一些可以从iOS14使用的事情。但是,我不能做我想做的事情,所以我想我还能做些什么。再次,可重复使用我尝试过了。执行我将首先发布实现的图像。 (Swift Playgrounds 演示)您可以像这样根据滚动获取坐标。让我们看看实现。1.
    03-08
  • Swift3.0 UICollectionView 删除,拖动
    Swift3.0 UICollectionView 删除,拖动
    UICollectionView实现了一下常见的新闻分类.  附有效果图 近期一直在深入学习swift,实现了CollectionView item的头东与删除,用的都是系统的一些函数方法,看起来比较直观. 第一步:class HotViewController: UIViewController,UICollectionViewDelegate,UICo
    02-09
  • swift -懒加载创建view
     // 只有外界访问到headerView的时候才会去执行闭包, 然后将闭包的返回值赋值给headerView    // 注意: 一定要记住闭包后面需要写上(), 代表执行闭包    //懒加载创建UIView    lazy var headerView: UIView = {        let view = UIView()
    02-09
  • Swift--非常好用的适合局部的代码约束
    // 哪个控件的哪个属性等于(大于、小于)另外一个控件的哪个属性乘以多少再加上多少 eg:let widthContraint = NSLayoutConstraint(item: messageLabel, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLa
    02-09
  • iOS打包framework - Swift完整项目打包Framework,嵌入OC项目使用
    iOS打包framework - Swift完整项目打包Framewor
    场景说明:-之前做的App,使用Swift框架语言,混合编程,内含少部分OC代码。-需要App整体功能打包成静态库,完整移植到另一个App使用,该App使用OC。-所以涉及到一个语言互转的处理,以及一些AppDelegate的代码减除变化。 --------------------------------
    02-09
  • Swift -- 官方文档Swift-Guides的学习笔记
    在经历的一段时间的郁闷之后,我发现感情都是虚伪的,只有代码是真实的(呸)因为看了swift语法之后依然不会用swift,然后我非常作死的跑去看官方文档,就是xcode里自带的help》documentation and API reference其中的swift里的guide这里主要总结一下里面每一
    02-09
  • Swift - 进度条(UIProgressView)的用法
     1,创建进度条1234var progressView=UIProgressView(progressViewStyle:UIProgressViewStyle.Default)progressView.center=self.view.centerprogressView.progress=0.5 //默认进度50%self.view.addSubview(progressView); 2,设置进度,同时有动画效果1p
    02-09
点击排行