FMDB 简介
FMDB 瞎说123
FMDB 是在 sqlite 的 Objective-C 版本。在 iOS 开发过程中,用到数据库的第三方大部分都会选择这个库,好早之前就用到了,这次抽了时间看看主要实现。
数据库所做的就是 CRUD 操作,那么 FMDB 要做的便是将 sqlite C API 中的 CRUD 操作以及其他数据库的操作转换成 Objective-C 的 API 。
为什么看 FMDB 源码?
(▼へ▼メ)
FMDB 的 REAMDME 大体浏览一遍,其对 ARC 环境编译期间的识别,以及其多线程的安全让我想探究一下他们是如何实现的,是通过什么样的技术去做到的,当然还有一部分就是我想看一下 FMDB 的单元测试是怎么做的,大概总结如下
- ARC 和 非 ARC 的编译器区分如何实现
- 多线程安全如何实现
- UnitTest 如何去做
- FMDB 如何支持 swift 呢?
尤其是最后这条,我没有看到 FMDB 有 Swift 的版本,那么他是如何支持 Swift 的呢?
FMDB 结构
读源码学习知识
这里记录的是学习到 FMDB 解决某些问题的方式
- ARC 和 非 ARC 区分
- 可变参数
- 参数约束
- 方法丢弃
FMDB 如何支持 非 ARC 和 ARC
1 | #if ! __has_feature(objc_arc) |
上面这部分代码便是如何实现 ARC 和 非 ARC 情况的宏定义,不错,就是通过宏定义来区分的,看一下实现的代码:
1 | + (instancetype)databaseQueueWithPath:(NSString *)aPath flags:(int)openFlags { |
在使用的地方,根据 ARC 或者 非 ARC 的情况,因为通过宏定义,如果是使用了 retain 的地方,那么在 ARC 下就是空的,如果使用了自动释放池,那么在 ARC 下便是原样儿不变,除此之外,还有 dealloc 方法:
1 | - (void)dealloc { |
FMDB 如何实现 Objective-C 方法可变参数(两种方式)
没有格式
1 | - (BOOL)executeUpdate:(NSString*)sql, ...; |
这个方法是 FMDB 中用来执行 sql 语句的,对于 sql 中的 insert 语句而言可以做如下执行:
1 | NSString *inputName = @"Tom"; |
这里就是可变参数了,而且参数没有限制。怎么实现的呢 ?
1 | - (BOOL)executeUpdate:(NSString*)sql, ... { |
通过 va_list 这种宏定义方式进行解析,而且 sql 语句貌似可以直接接受 va_list 参数
有格式
什么是有格式呢 ?
1 | - (BOOL)executeUpdateWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); |
怎么使用呢 ?
1 | [db executeUpdateWithFormat:@"insert into Teacher (name,age,sex) values (%@, %d, %d)",inputName,inputAge,selectGender]; |
可以看到,这种模式我们并不陌生,我们称之为:格式化字符串。像 NSString 就有这么一个方法,我们经常在用:
1 | + (instancetype)stringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); |
这里是在方法声明的后面添加了 NS_FORMAT_FUNCTION(1,2) 一个宏定义便 OK 了,那么如何解析这些参数呢?
1 | - (BOOL)executeUpdateWithFormat:(NSString*)format, ... { |
是的和上面的解析方式一样,但是我们要看到如何解析到字符串和数字呢?
1 | - (void)extractSQL:(NSString *)sql argumentsList:(va_list)args intoString:(NSMutableString *)cleanedSQL arguments:(NSMutableArray *)arguments { |
是的,就是这么一个一个的解析出来的
参数约束
1 | NS_ASSUME_NONNULL_BEGIN |
这一对宏中包含的方法中的参数都是必须传入的,否则会报警告,也就是参数不能为 nil。如果,打算让参数可以为 nil 那么就必须在参数类型后面添加 _Nullable, FMDB 初始化方法可以不传入 path ,如上实现。
方法丢弃
这在系统 API 中也经常看到,
1 |
|
FMDB 如何支持 Swift 呢?
FMDB 的单元测试
如何看源码?
带着问题去看,带着好奇心去看,快乐的看!
看源码是一件很痛苦的事情,因为这就像一场陌生的旅游,或者是到了别人家里一样!比如有一天别人说:
”啊,那么土地真的很美丽,很有魅力,大家都说它多好多好”
你听说了之后,也不知道自己感不感兴趣,也不知道它哪里美,更不知道你去了要做什么,只知道别人说去过那里的人都很 NB ,所以你去了,这不是一场旅行,这是一场灾难,绝对的,因为你对它太陌生了,陌生到你处处碰壁,无路可走。
很多时候,我们觉得漫无目的的浏览风光觉得很好,但是,当你意识到生命的短暂,时间的流逝的时候,让你这么做,那绝对绝对是谋杀了。记得以前总觉得自己总是被枷锁锁住,后来我将枷锁打破,然后自己慢慢的静待时光流逝,我以为这种感觉会很好,但是当时间流逝了一段时间之后,我感到疲惫,感到不安,这就如同我们在看源码的时候,漫无目的的去看,都知道这个框架好,那个代码写的优美,但是你真的懂得怎么去欣赏这里的景色了么?
当你想去买房子的时候,你才会去关注房价,关注房屋设计,关注各个城市之间的区别等等。为此,你猜了解到了,原来房子需要这样那样,原来周边环境也很重要,原来这种材料是一般般的等等的问题。而如果你从未打算去买房子,那么别人邀你一起去看房子,即使那房子再美,我想你看到的也就是那句 “房子不错” 其他的你也许真的真的看不出来了。
所以,如果你打算去看一个源码,那么最好最好准备,你要得到什么,为什么去看,相信我,如果你知道了这些,真的会事半功倍!
就如同现在区块链很火,很多人都去看,算法也很火,很多人都去学,我看到好多人都去分享那些xxxx课程,xxxx讲座,xxxx多少天让你了解,我没有去看过,我只在乎那些我需要的东西。
就如同,我要实现可变参数,我要实现一个库支持 Objective-C 和 Swift 一样,just this!
还有一个原因就是,你永远不可能知道第三方库为什么要写成这样?真的,第三方库为什么要实现这样或者那样的需求,这些事情要问作者,而作者也不会知道,你我都是 coding 的,我们都知道需求写完了之后的事情就是没有问题我们便会会提起!所以好多东西本来便没有了来源,你再怎么看也是那个样子,所以索性让第三方库围绕着你走,你要什么便到里面去寻找就 OK 了。