欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~

作者:sanhuazhang,此文发布在微信终端开发团队的专栏

WCDB 作为微信的终端数据库,从 2017.6 开源至今,共迭代了 5 个版本。我们一直关注开发者们的需求,并不断优化性能,新增如全文搜索等常用的功能。而这其中,呼声最高的莫过于 对 Swift 的支持。

WCDB ObjC 版本的实现中,由于引入了 C++ 代码,并不能直接 bridge 到 Swift。因此,我们从 9 月份开始就着手使用原生的 Swift,重写 WCDB。并于 10.10 和 11.8 分别在开发者群内发布了 alpha 和 beta 版进行测试。

今天,终于可以正式发布 WCDB Swift 的第一个正式版本了。

WCDB Swift 约有 1.5w 行代码,使用 Pure Swift 编写,几乎不包含 Cocoa 的代码。且与 ObjC 版保持完全一致的功能。

模型绑定

WCDB Swift 的模型绑定,基于 Swift 4.0 的 Codable 协议实现。通过建立 Swift 类型与数据库表之间的映射关系,使得开发者可以通过类对象直接操作数据库。

语言集成查询

语言集成查询深度结合了 Swift 和 SQL 的语法,使得纯字符串的 SQL 可以以代码的形式表达出来。结合代码提示及纠错,极大地提高开发效率。

同时,由于 Swift 的语法 比 Objective-C 更加简洁,并有更强大的范型和类型推导,使得 WCDB 接口不仅更易编写,而且更易读易维护。

类似 Sample.Properties.identifier > 0 的语法,其返回值并不为 Bool,而是语言集成查询的 Expression 对象,WCDB 会根据这个语句,去进行 SQL 的查询。同时,通过类型的定义,Swift 即可推导出 WCDB 查询的结果为 Sample 类。

语言集成查询同时内建了反注入机制,可以避免第三方从输入框注入 SQL,进行预期之外的恶意操作。

深入 SQLite 源码的性能优化

WCDB 基于 SQLite 开发,我们在之前的文章介绍过其对 SQLite 源码进行的性能优化,以适配移动终端的场景。同样地,这部分优化 Swift 版本也能享受到。

线程安全且并发

WCDB Swift 不仅可以安全地在任意线程进行数据库操作,且其内部会智能地根据操作类型调配资源,使其能够并发执行,进一步提升效率。

加密

基于 SQLCipher 的加密机制,可以为客户端数据安全提供一定程度的保障。

字段升级

数据库模型与类定义绑定,使得字段的增加、删除、修改都与类变量的定义保持一致,不需要开发者额外地管理字段的版本。

模型绑定中新增了 newColumn 字段,该字段也会被自动创建到数据库表中,开发者不需要手动管理。

全文搜索

WCDB Swift 提供简单易用的全文搜索接口,并包含适配多种语言的分词器,使得数据搜索更精准。

损坏修复

内建的修复工具可以在系统错误、磁盘故障等情况下,尽最大限度地将损坏的数据找回并导出。

Pure Swift

模型绑定对语言的依赖性很大。由于 ObjC 其强大的消息转发机制,使得 WCDB 实现起来并没有太大的问题。然而,动态性却恰恰是 Swift 一直为人诟病的地方。

最省事的解决方案就是,直接引入 Cocoa,所有的问题都将不再是问题。然而,这并不是我们所期望的。

理性分析可以得出,一方面,全面的动态化会拖累 Swift 的性能,另一方面,这也会使得 Swift 的原生类型难以享受到模型绑定。

但我们的理由可能更感性一些 --- 情怀。称之为强迫症也好,代码洁癖也罢,Swift with Cocoa 总让人心里有那么一丝别扭。因此,我们决定寻找 Swift 原生的解决方案。

WCDB 的模型绑定对语言有两点依赖:

1. Accessor。ObjC 版本使用 selector 的 IMP 指针,使得 WCDB 可以获取变量的值,并插入到数据库中,或从数据库中获取数据写入到变量。

2. 数据库字段的映射。ObjC 版本使用宏定义,使得 WCDB 可以通过className.propertyName 的方式进行语言集成查询的操作。

KeyPath

我们最初盯上的是 Swift 的 KeyPath 的机制,它通过 \ 的语法,可以直接对变量进行读写操作,且语法上也与 className.propertyName 类似。

一个难题是,KeyPath 在不引入 Cocoa 的情况下,是并不提供 property 的名称,这就无法通过 KeyPath 直接映射数据库的字段。

Swift 也有一个相关的 SR 在讨论这个问题。

显然,我们不可能等待这个特性实现了再去做 WCDB Swift。因此我们尝试使用“不常规”的方法,获取到 KeyPath 对应的 property 名称。

Mirror 是 Swift 里的反射类型,它可以遍历每个变量,获取其名称和值,但不能对变量写入数据。因此我们可以通过 KeyPath 对变量设一个独一无二的特征值,然后再通过Mirror 遍历变量,导出与特征值相同的 property 名称。

这个“不常规”的用法在大部分情况下能够生效,但对于 class 和 struct 相互嵌套的变量,容易因为内存混乱导致 crash。

Codable

KeyPath 的方案不够完善的情况下,我们转投了 Codable 协议。它是 Swift 4.0 新增的特性,本质是编译前根据定义生成代码,以完成序列化和反序列化的任务。

对应到 WCDB,将数据库的字段读写到变量中,其本质就是一个序列化和反序列化的过程,而 CodingKeys 也可能可以用于语言集成查询中的字段映射。

然而,由于这个特性还很新,还没有太多文档对其进行深入介绍,尤其是自定义 Encoder 和Decoder 这部分。

所幸的是,Swift 本身就是开源的。因此,我们参考 swift-corelibs-foundation 中的JSONEncoder 和 JSONDecoder,实现了 TableEncoder 和 TableDecoder,并通过CodingKeys 的定义,映射数据库中的字段。

最终维护了我们对 Pure Swift 的坚持。

微信也转向 Swift 开发了吗?

相信这会是大家非常关心的问题。然而,很遗憾,目前还没有。不仅微信,国内外大部分 app 都还没有完全转向Swift,但显然这是个趋势。

Google 在 11 月 fork 了 Swift。

大家犹豫不定的原因都大同小异:ABI不稳定,需要将二进制打包进去,增大app体积;某些方面性能还不够好,而且现在多数是与 ObjC 混编,将进一步拉低性能 等等。

而这其中一个很重要的原因就是,Swift 的基础设施还不完善,还难以支撑其大型 app 的开发。而 WCDB Swift 就是这类基础设施之一。

因此,先有 WCDB Swift,未来才有用 Swift 编写微信的可能,这逻辑没毛病。

另一方面,没有微信的上线机制的保护和庞大的用户量的验证,我们需要确保 WCDB Swift 的稳定性。因此,在 WCDB Swift 的第一版本,我们就提供了相对完善的测试用例,用例的代码覆盖率为 91.34%,能够触达绝大部分使用场景。

更多 WCDB Swift 的教程文档、代码样例,包括源码,直接到 Github 的 Tencent/wcdb 了解。

我们一起期待 Swift 成为开发者的首选的那一天。

相关阅读

微信终端开发团队:新年新语言,WCDB Swift的更多相关文章

  1. [Android开发学iOS系列] 语言篇: Swift vs Kotlin

    Swift vs Kotlin 这篇文章是想着帮助Android开发快速学习Swift编程语言用的. (因为这个文章的作者立场就是这样.) 我不想写一个非常长, 非常详尽的文章, 只是想写一个快速的版 ...

  2. 【腾讯Bugly干货分享】微信终端跨平台组件 mars 系列(一) - 高性能日志模块xlog

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ff5932cde42f1f03de29b1 本文来源: 微信客户端开发团队 ...

  3. 【沙龙报名中】与微信&云开发官方团队零距离互动,揭秘爆款微信小游戏背后的技术!

    有人说 微信小程序游戏的百花齐放 活像十几年前的4399小游戏称霸互联网的景象 " 歪,斗地主吗,三缺二, 不用下app,小程序就能玩,我保证不抢地主让你抢!" ...... &q ...

  4. Swift 新语言开发

    全书文件夹: 一.Welcome to Swift 二.Language Guide 三.Language Reference /* 译者的废话: 几个小时前熬夜看了WWDC,各种激动,今年非常有料啊 ...

  5. 承接微信小程序外包 H5外包就找北京动点软件开发团队

    承接小程序外包 微信小程序外包 H5外包 就找北京动点软件 长年承接微信小程序.微信公众号开发 全职的H5开发团队,开发过几十款微信小程序公众号案例 欢迎来电咨询,索取案例! QQ:372900288 ...

  6. H5外包 微信小程序外包 小程序外包 就找北京动点开发团队

    长年承接微信小程序.微信公众号开发 全职的H5开发团队,开发过几十款微信小程序公众号案例 欢迎来电咨询 QQ:372900288 微信:liuxiang0884 TEL:13911652504

  7. 【腾讯Bugly干货分享】微信终端跨平台组件 Mars 系列 - 我们如约而至

    导语 昨天上午,微信在广州举办了微信公开课Pro.于是,精神哥这两天的朋友圈被小龙的"八不做"刷屏了.小伙伴们可能不知道,下午,微信公开课专门开设了技术分论坛.在分论坛中,微信开源 ...

  8. .net之微信企业号开发(一) 所使用的环境与工具以及准备工作

    前言 一直以来,从事的是.net winform的编程,虽然对移动互联这块很感兴趣,但是由于现有的工作和移动互联之间隔的太远,也就没有时间和精力好好的去研究和实现.今年年初辞职了,刚好朋友那里希望建立 ...

  9. 【腾讯Bugly干货分享】微信终端跨平台组件 mars 系列(二) - 信令传输超时设计

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/9DJxipJaaBC8yC-buHgnTQ 作者简介: ...

随机推荐

  1. java变量和作用域以及成员变量的默认初始化

    Java中的变量有成员变量和局部变量,定义在类中方法之外的变量成为成员变量或者成员字段(域),表示一个类所具有的属性,定义为类的成员变量的变量的作用于是整个类,该变量在定义的时候不需要初始化,在使用前 ...

  2. Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验,使用消息资源文件对消息国际化

    导包和配置 导入 JSR 303 的包.hibernate valid 的包 <dependency> <groupId>org.hibernate.validator< ...

  3. iOS 开发人员不可缺少的75个工具

    原文出处: Ben Scheirman 译文出处: Njuxjy 假设你去到一位熟练的木匠的工作室,你总是能发现他/她有一堆工具来完毕不同的任务. 软件开发相同如此. 你能够从软件开发人员怎样使用工具 ...

  4. Creational模式之Builder模式

    1.意图 将一个复杂对象的构建与它表示分离,使得相同的构建过程能够创建不同的表示. 查看很多其它请点击 2.别名 无 3.动机 一个RTF(Rich Text Format)文档交换格式的阅读器应能将 ...

  5. 在Intellij里使用Erlang依赖库

    这里以protobuffs为例,记录一下环境的配置,发现这种东西中文的资料真的不多,无论是分享还是记录都是很好的 1.创建一个文件夹名use_proto, 配置rebar.config文件如下: {d ...

  6. Java快速排序算法

    快速排序算法思想: 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一 ...

  7. Java二维数组的概念和使用方法

    二维数组 数组的数组---二维数组的每一个元素是一个一维数组 定义格式 数据类型[][] 数组名 = new 数据类型[二维数组的长度/包含的一维数组的个数][每个一维数组的长度]; int[][] ...

  8. (转)Maven依赖的jar包下载不了、jar更新不了的解决办法

    场景一: 使用Maven的同学可能偶尔会遇到这种情况:pom.xml中依赖了项目需要的某个jar文件,但是使用Maven –> update project 还是没办法下载该jar到项目中,你可 ...

  9. Unity优化之GC——合理优化Unity的GC

      转载请标明出处http://www.cnblogs.com/zblade/ 最近有点繁忙,白天干活晚上抽空写点翻译,还要运动,所以翻译工作进行的有点缓慢 =.= PS: 最近重新回来更新了一遍,文 ...

  10. 合并查询结果集UNION(去重), UNION ALL(不去重),INTERSECT(交集),MINUS(差集,第一个结果集减去第二个结果集,第一个结果集中不在第二个结果集中的记录行),[NOT] EXIST

    MINUS配合[NOT] EXIST使用可以查询出包含符合某个条件的多记录的其他记录, 举例: 顾客A买了商品2.4.6 顾客B买了商品1.2.4 顾客C买了商品4.6 顾客D买了商品1.2.4.6 ...