美文网首页
FMDB源码系列(一)

FMDB源码系列(一)

作者: Invoker_M | 来源:发表于2018-04-25 17:01 被阅读0次

    FMDB有FMDatabase、FMDatabaseQueue、FMResultSet这三个重量级的类。

    • FMDatabase
      用来表示sqlite3数据库对象。
    • FMDatabaseQueue
      用来执行线程安全的多线程数据库操作。
    • FMResultSet
      数据库对象根据sql语句进行操作后返回的结果集对象。

    笔者对于FMDB源码的探究首先从这三个类入手,由于FMDatabaseQueue引用到了FMDatabase,而FMDatabase又引用到了FMResultSet。所以笔者决定通过FMResultSet -> FMDatabase -> FMDatabaseQueue这样的顺序来解读这三个类。

    FMDB中用到的宏

    在解读源码之前,我们先来看一下FMDB中常用到的一些宏。

    • NS_ASSUME_NONNULL_BEGIN&NS_ASSUME_NONNULL_END
      在代码中,包含在这两个宏中间的属性、方法均会被加上一个nonnull的标记。如果想要其中的属性或方法不受此约束,则在对应的属性中加入nullable即可
      我们可以点击看到这两条宏所定义的语句为
    #ifndef NS_ASSUME_NONNULL_BEGIN
    #define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
    #endif
    #ifndef NS_ASSUME_NONNULL_END
    #define NS_ASSUME_NONNULL_END   _Pragma("clang assume_nonnull end")
    #endif
    

    _Pragma看上去是不是很熟悉,我们经常在代码中写

    #pragma mark - 自定义字符串
    

    这是C++中的杂注指令,关于这点,可以看看这里
    这意味着,我们这样写也是有效的

    #pragma clang assume_nonnull begin
    #pragma clang assume_nonnull end
    

    • FMDB_SQLITE_STANDALONE
      这个宏是在FMDB中的podspec中定义的
    s.subspec 'standalone' do |ss|
        ss.xcconfig = { 'OTHER_CFLAGS' => '$(inherited) -DFMDB_SQLITE_STANDALONE' }
        ss.dependency 'sqlite3'
        ss.source_files = 'src/fmdb/FM*.{h,m}'
        ss.exclude_files = 'src/fmdb.m'
      end
    

    目前FMDB中设定的默认子文件夹是'standard',并不是standalone或者standalone-fts。所以这个宏在工程中都返回NO。


    • OS_OBJECT_USE_OBJC
      这个宏在FMDB中用于
    #if OS_OBJECT_USE_OBJC
            #define FMDBDispatchQueueRelease(__v)
        #else
            #define FMDBDispatchQueueRelease(__v) (dispatch_release(__v));
        #endif
    

    OS_OBJECT_USE_OBJC是针对过去iOS 6.0以下版本的GCD并不具备ARC所产生的。所以当OS_OBJECT_USE_OBJC返回0时,GCD需要使用dispatch_release()来释放内存。


    • NS_RETURNS_NOT_RETAINED
      这个宏用于标注带返回值的方法,并且还有一个兄弟叫做NS_RETURNS_RETAINED。在FMDB中只有2个方法标注了这个宏,并且都在注释中写上了Warning。
    - (NSData * _Nullable)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED;
    
    - (NSData * _Nullable)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED;
    

    NS_RETURNS_NOT_RETAINED表示这个方法返回的对象,不需要被release,而NS_RETURNS_RETAINED则表示方法所返回的对象需要被release。


    最后在提一下__has_feature这个方法,在Clang中是这么解释的
    HasFeature - Return true if we recognize and implement the feature specified by the identifier as a standard language feature.
    即为:如果我们识别并实现标识符指定的功能作为标准语言功能,则返回true(google翻译,doge)。
    在Clang中它定义了非常多的关键词,有兴趣的朋友可以去看看PPMacroExpansion.cpp,从1094行开始。


    再贴一下FMDB中所使用的Sqlite3错误码

    #define SQLITE_OK           0   /* 成功 | Successful result */
    /* 错误码开始 */
    #define SQLITE_ERROR        1   /* SQL错误 或 丢失数据库 | SQL error or missing database */
    #define SQLITE_INTERNAL     2   /* SQLite 内部逻辑错误 | Internal logic error in SQLite */
    #define SQLITE_PERM         3   /* 拒绝访问 | Access permission denied */
    #define SQLITE_ABORT        4   /* 回调函数请求取消操作 | Callback routine requested an abort */
    #define SQLITE_BUSY         5   /* 数据库文件被锁定 | The database file is locked */
    #define SQLITE_LOCKED       6   /* 数据库中的一个表被锁定 | A table in the database is locked */
    #define SQLITE_NOMEM        7   /* 某次 malloc() 函数调用失败 | A malloc() failed */
    #define SQLITE_READONLY     8   /* 尝试写入一个只读数据库 | Attempt to write a readonly database */
    #define SQLITE_INTERRUPT    9   /* 操作被 sqlite3_interupt() 函数中断 | Operation terminated by sqlite3_interrupt() */
    #define SQLITE_IOERR       10   /* 发生某些磁盘 I/O 错误 | Some kind of disk I/O error occurred */
    #define SQLITE_CORRUPT     11   /* 数据库磁盘映像不正确 | The database disk image is malformed */
    #define SQLITE_NOTFOUND    12   /* sqlite3_file_control() 中出现未知操作数 | Unknown opcode in sqlite3_file_control() */
    #define SQLITE_FULL        13   /* 因为数据库满导致插入失败 | Insertion failed because database is full */
    #define SQLITE_CANTOPEN    14   /* 无法打开数据库文件 | Unable to open the database file */
    #define SQLITE_PROTOCOL    15   /* 数据库锁定协议错误 | Database lock protocol error */
    #define SQLITE_EMPTY       16   /* 数据库为空 | Database is empty */
    #define SQLITE_SCHEMA      17   /* 数据结构发生改变 | The database schema changed */
    #define SQLITE_TOOBIG      18   /* 字符串或二进制数据超过大小限制 | String or BLOB exceeds size limit */
    #define SQLITE_CONSTRAINT  19   /* 由于约束违例而取消 | Abort due to constraint violation */
    #define SQLITE_MISMATCH    20   /* 数据类型不匹配 | Data type mismatch */
    #define SQLITE_MISUSE      21   /* 不正确的库使用 | Library used incorrectly */
    #define SQLITE_NOLFS       22   /* 使用了操作系统不支持的功能 | Uses OS features not supported on host */
    #define SQLITE_AUTH        23   /* 授权失败 | Authorization denied */
    #define SQLITE_FORMAT      24   /* 附加数据库格式错误 | Auxiliary database format error */
    #define SQLITE_RANGE       25   /* 传递给sqlite3_bind()的第二个参数超出范围 | 2nd parameter to sqlite3_bind out of range */
    #define SQLITE_NOTADB      26   /* 被打开的文件不是一个数据库文件 | File opened that is not a database file */
    #define SQLITE_ROW         100  /* sqlite3_step() 已经产生一个行结果 | sqlite3_step() has another row ready */
    #define SQLITE_DONE        101  /* sqlite3_step() 完成执行操作 | sqlite3_step() has finished executing */
    

    下一篇我们将走进FMResultSet中的世界,一探究竟。

    相关文章

      网友评论

          本文标题:FMDB源码系列(一)

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