美文网首页iphone X ios 11
iOS开发之FMDB的使用

iOS开发之FMDB的使用

作者: 笑忘书丶 | 来源:发表于2016-04-01 15:22 被阅读990次

    开发中,使用到数据库一般会使用FMDB这个第三方库,来简化使用。FMDB是iOS平台的SQLite数据库框架,它以OC的方式封装了SQLite的C语言API。使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码,对比苹果自带的Core Data框架,更加轻量级和灵活,提供了多线程安全的数据库操作方法,有效地防止数据混乱。

    1. FMDB的核心类

    FMDB有三个主要的类:
    FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句。
    FMResultSet:使用FMResultSet执行查询后的结果集。
    FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的。

    2. FMDB的方法介绍

    2.1 更新update

    在FMDB中,除查询以外的所有操作,都称为“更新”。create、drop、insert、update、delete等

    使用executeUpdate:方法执行更新
    - (BOOL)executeUpdate:(NSString*)sql, ...
    - (BOOL)executeUpdateWithFormat:(NSString*)format, ...
    - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
    
    2.2 查询query
    查询方法
    - (FMResultSet *)executeQuery:(NSString*)sql, ...
    - (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
    - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
    示例
    // 查询数据
    FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_student"];
    // 遍历结果集
    while ([rs next]) {
        NSString *name = [rs stringForColumn:@"name"];
        int age = [rs intForColumn:@"age"];
        double score = [rs doubleForColumn:@"score"];
    }
    

    3. FMDB的使用

    和c语言框架一样,FMDB通过指定SQLite数据库文件路径来创建FMDatabase对象,但FMDB更加容易理解,使用起来更容易,使用之前一样需要导入sqlite3.dylib。

    3.1 文件路径有三种情况

    (1)具体文件路径
      如果不存在会自动创建
    (2)空字符串@""
      会在临时目录创建一个空的数据库
      当FMDatabase连接关闭时,数据库文件也被删除
    (3)nil
      会创建一个内存中临时数据库,当FMDatabase连接关闭 时,数据库会被销毁
      当FMDatabase连接关闭时,数据库文件也被删除

    3.2 打开数据库方法如下
        var db: FMDatabase?
        /**
        *  打开数据库
        */
        func openDB(DBName: String)
        {
            // 1.根据传入的数据库名称拼接数据库路径
            let path = DBName.docDir()
            
            // 2.创建数据库对象
            db = FMDatabase(path: path)
            
            // 3.打开数据库
            // open方法特点: 如果指定路径对应的数据库文件已经存在, 就会直接打开
            //              如果指定路径对应的数据库文件不存在, 就会创建一个新的
            if !db!.open()
            {
                print("打开数据库失败")
                return
            }
            
            // 4.创建表
            creatTable()
        }
        
        private func creatTable()
        {
            // 1.编写SQL语句
            let sql = "CREATE TABLE IF NOT EXISTS T_Person( \n" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
                "name TEXT, \n" +
                "age INTEGER \n" +
            "); \n"
            
            // 2.执行SQL语句
            // 注意点: 在FMDB中除了查询意外, 都称之为更新
            if db!.executeUpdate(sql, withArgumentsInArray: nil)
            {
                print("创建表成功")
            }else
            {
                print("创建表失败")
            }
        }
    

    4. FMDatabaseQueue的使用

    如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。 应用中不可在多个线程中共同使用一个FMDatabase对象操作数据库,这样会引起数据库数据混乱。 为了多线程操作数据库安全,FMDB使用了FMDatabaseQueue,使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。 在闭包中操作数据库,而不直接参与FMDatabase的管理。

    4.1 创建打开数据库
        var dbQueue: FMDatabaseQueue?
        
        /**
        *  打开数据库
        */
        func openDB(DBName: String)
        {
            // 1.根据传入的数据库名称拼接数据库路径
            let path = DBName.docDir()
            
            // 2.创建数据库对象
            // 注意: 如果是使用FMDatabaseQueue创建数据库对象, 那么就不用打开数据库
            dbQueue = FMDatabaseQueue(path: path)
            
            // 4.创建表
            creatTable()
        }
        
        private func creatTable()
        {
            // 1.编写SQL语句
            let sql = "CREATE TABLE IF NOT EXISTS T_Person( \n" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
                "name TEXT, \n" +
                "age INTEGER \n" +
            "); \n"
            
            // 2.执行SQL语句
            dbQueue!.inDatabase { (db) -> Void in
                db.executeUpdate(sql, withArgumentsInArray: nil)
            }
        }
    
    4.2 插入记录
        /**
        插入一条记录
        */
        func insertPerson()
        {
            
            assert(name != nil, "必须要给name赋值")
            
            // 1.编写SQL语句
            let sql = "INSERT INTO T_Person" +
            "(name, age)" +
            "VALUES" +
            "('\(name)', \(age));"
    
            // 2.执行SQL语句
            // 只要在inTransaction闭包中执行的语句都是已经开启事务的
            /*
            第一个参数: 已经打开的数据库对象
            第二个参数: 用于设置是否需要回滚数据
            */
            SQLiteManager.shareManager().dbQueue?.inTransaction({ (db, rollback) -> Void in
                if !db.executeUpdate(sql, withArgumentsInArray: nil)
                {
                    // 如果插入数据失败, 就回滚
                    // OC中的写法 : *rollback = YES;
                    // Swift中的写法: rollback.memory = true
                    rollback.memory = true
                }
            })
        }
    
    4.3 查询
        // MARK: - 执行数据源CRUD的操作
        class func loadPersons(finished: ([Person])->())
        {
            let sql = "SELECT * FROM T_Person;"
            
            
            SQLiteManager.shareManager().dbQueue?.inDatabase({ (db) -> Void in
                
                let res = db.executeQuery(sql, withArgumentsInArray: nil)
                
                // next取出一行数据
                var models = [Person]()
                while res.next()
                {
                    let p = Person()
                    let num = res.intForColumn("id")
                    let name = res.stringForColumn("name")
                    let age = res.intForColumn("age")
                    print("num = \(num), name = \(name), age = \(age)")
    
                    p.id = Int(num)
                    p.name = name
                    p.age = Int(age)
                    models.append(p)
                }
                
                finished(models)
            }) 
        }
    

    相关文章

      网友评论

        本文标题:iOS开发之FMDB的使用

        本文链接:https://www.haomeiwen.com/subject/qyjelttx.html