首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Swift在好大夫APP医患两端的打怪升级

swift作为苹果的亲儿子,从2014年开始,在6年的发展过程中,终于在2019年3月份迎来了ABI(Application Binary Interface)的稳定。

背景

ABI的稳定意味着Binary接口稳定,也就是运行的时候只要是通过swift 5或者以上的编译器编译出来的binary,就可以跑在任意的swift 5.0及以上的runtime上。这样,我们就不需要像以前那样在app里面放一个swift runtime,Apple会把相应的ABI整合到iOS或者macOS中。同时App的尺寸会变小,在iOS12.2以上系统,会预装swift5 runtime,所以不在需要swift的库,它们会从app bundle中被删除,对于iOS12.2以下的系统,还是照旧需要引入。同时因为系统集成了swift,app启动的时候也就不需要额外加载swift,在新系统中会更加的节省内存空间。

对于好大夫的医患两端,在这时接入swift是一个不可多得的好机会。那么,从好大夫的iOS客户端团队角度出发,接入swift需要有哪些准备工作?基础框架如何设计?如何解决在swift开发中出现的问题?这些都会在下文中一一解答。

接入swift的准备工作

好大夫的iOS客户端代码年份非常久远,整体使用Objective-C编写,最早的代码可以追溯到2011年8月份,对于接入swift来说,首先需要进行技术调研,什么版本的swift适合好大夫客户端,而不是一味的追求最新的swift版本。其次,对于swift三方框架的调研,国内的swift社区活跃度并不是特别高,相反国外的swift社区反而更加的活跃,从github上的Alamofire网络库到Uber早已使用swift重构客户端,可见swift在过国外早已盛行已久。

通过调研,swift在开发效率和性能上明显优于Objective-C,苹果开发者官网上各种Programming Guide也已经以swift作为首要显示语言,从苹果对swift的推广来看,如果我们一直坚守Objective-C阵营,在未来苹果强制推进swift,对我们来说冲击还是比较大的。WWDC2019中,苹果同时推出了swiftUI,正式统一了Apple全平台UI开发解决方案,未来属于swift,可见好大夫iOS客户端接入swift刻不容缓。

基础框架设计

iOS客户端整体采用组件化的架构,使用cocoapods导入各个组件,业务之间通过中间件进行通信,基础组件包括网路库、图片库、支付库等。在接入swift之后,虽然基础私有库可以通过修改podspec文件进行swift私有库调用,但是为了统一和壮大iOS客户端的swift生态系统,对于部分私有库进行了swift化重构,生成一套专供swift调用的基础库,当然不是所有的私有库都进行了重构,而是根据具体的业务需求以及公司未来发展综合考虑,对一些工程中经常用到的宏定义,遍历构造函数以及视图约束框架等进行了swift化。

对于UI常用控件,网络库,图片库,支付库等,如果进行重构,则会出现影响范围较大,测试耗时很长,影响项目迭代,拿UI控件库来说只是进行了podspec文件修改,使其支持了swift私有库的调用,同时如果有新增的基础控件,首选swift语言来编写,减少Objective-C代码的使用。

经过一年时间的沉淀,iOS客户端目前全量swift业务有直播业务、留言板业务,其他的业务的主流业务也已经使用了swift和OC混编的方式进行开发。

推进工程swift化遇到的问题

传统Objective-C项目接入swift一些问题始终是绕不过去的,如:

  • 主工程或者模块化中swift和Objective-C的混编怎么实现
  • Module系统
  • swift代码的规范性怎么解决

一、swift和OC混编

针对上面的第一个问题,我们分为两种情况,第一种情况为App Target内部swift和OC混编,对于好大夫的医患两端来说之前一直使用Objective-C编写,所以在创建第一个swift文件时,会提示生成一个bridging header文件,点击create即可。

在swift文件中如果需要引入某个OC类,将需要使用的OC类在bridging文件进行#import即可。在OC类中如果需要引入swift文件,只需要在OC类中引入import “ProductModuleName-Swift.h”,其中ProductModuleName表示当前Target的名称。ProductModuleName-Swift.h文件为编译产物,可以看到该文件将swift文件中的代码生成为对应OC中的interface和implementation。

第二种情况为模块内部进行swift和OC混编,或者OC私有库需要提供给外部的swift文件或者swift私有库使用,针对这种情况我们可以统一配置,好大夫客户端采用的cocoapods方式引入组件,所以通过对组件podspec进行配置,添加 s.pod_target_xcconfig = {‘DEFINES_MODULE’ => ‘YES’} 将组件模块进行module化,可以使用cocoapods自动生成的umbrella.h文件或者自己新建一个 umbrella header 将需要暴露给swift调用的ObjC头文件在这个 umbrella header 中导入,在需要调用的swift文件中直接 import Module 即可。

二、Module系统

2.1 LLVM Module系统

既然说到了OC和swift混编,那么不得不提苹果在2012年11月提出LLVM的Module系统,简单讲就是用树形的结构化描述来取代以往#include,例如传统的#include <stdio.h>变成了 import std.io,逼格更高,这样做的好处主要有:

  • 语义上完整描述了一个框架的作用;
  • 提高编译时的可扩展性,同一模块只需要编译或导入一次,避免了头文件的多次引用、解析;
  • 减少碎片化,每个模块只处理一次,环境的变化不会导致不一致;
  • 对工具友好,工具(语言编译器)可以获取更多关于 module 的信息,比如链接库,比如语言是 C++ 还是 C;

2.2 modulemap文件

modulemap文件就是对一个框架,一个库所有文件的结构化描述,默认文件名是module.modulemap。如下图,可以看到使用 umbrellar header 关键字导入 HDFIMComponent-umbrella.h 中所有的.h文件。

umbrellar header关键字的意思为 Master Header File,可以使用

#import <UIKit/UIKit.h>

替代

#import <UIKit/UIViewController.h>
#import <UIKit/UILabel.h>
#import <UIKit/UIButton.h>
#import <UIKit/UIDatePicker.h>

2.3 Swift Module

项目中的每一个Target(无论是framework还是app),就叫做一个Swift Module。这是Swift分发代码的方式,我们可以通过import命令,来使用定义在其他Module中的代码,而每个Module意味着:

  • 一个和Module同名的命名空间
  • 一个独立的访问控制范围

对第一条来说,这也就是为什么在一个项目中,定义在不同Swift文件中的类可以在不同的文件中直接使用而不需要include的原因,因为它们本身就在同一个namespace里。

对于第二条来说,当我们通过import在项目中引入一个module时,就相当于打开了这个module对应的命名空间,就可以使用这个module中所有标记为public或者open的代码。

三、规范swift代码

不同的人有不同的编码习惯,导致了工程中代码风格的多样性,为了提供swift代码的可读性以及统一性,iOS客户端引入了swiftlint,swiftlint是Realm开源的一个加强检查swift语言规范的库,可以满足强迫症的所有幻想,通过对swift代码进行扫描,统一编码风格,从每一个文件到每一个函数,甚至每一个变量都进行规范,将swiftlint扫描后的结果接入到SonarQube,使用网页进行展示,方便分类修改,将具体的代码分配给对应的负责人,严格按照要求进行修改,保证客户端swift代码坏味道为0。

未来规划

swift是一门优秀的编程语言,就目前苹果主推swift语言以及编程语言排行榜上swift已经从18位上升到12位,可见未来国内swift语言也将会盛行。接入swift简单,但是如果想要完美的兼容当前工程并非一件容易的事,只有选择正确的方式,合适的解决方案才能将swift与原工程成功融合在一起。

好大夫iOS客户端目前已经全量使用swift进行开发,计划每年做新系统适配时会升级swift版本,紧跟时代的发展。后续接入swift package manager替代cocoapods、声明式UI替代现有命令式UI。

作者介绍:

陶庆玮:好大夫iOS开发工程师,主要负责组件化工程、基础库开发和客户端稳定性相关工作,以及Swift语言落地。

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/oSLO9coMAmNLV51RCpFY
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券