写点什么

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

  • 2020-09-23
  • 本文字数:3217 字

    阅读完需:约 11 分钟

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 以上系统,会预装 swift 5 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 语言落地。


2020-09-23 08:004876

评论

发布
暂无评论
发现更多内容

openGauss都做了哪些算子优化工作?

openGauss

Node.js实现JWT应用到服务器

格斗家不爱在外太空沉思

node.js 三周年连更

软件测试/测试开发丨基于 JMeter 完成 Dubbo 接口的测试

测试人

dubbo 软件测试 Jmeter 自动化测试 测试开发

慌了?ChatGPT吃我的饭,还要掀我碗

引迈信息

AI 低代码 ChatGPT JNPF

MobTech ShareSDK|如何从分享到回流

MobTech袤博科技

盘点 8 款好用的 API 接口文档管理工具

Liam

程序员 接口文档 API 接口规范 接口编写

5 分钟带你小程序入门 [实战总结分享]

程序员海军

小程序 微信小程序 前端 三周年连更

论程序员的为码之“道”

酱紫的小白兔

RabbitMQ组件介绍

穿过生命散发芬芳

RabbitMQ 三周年连更

前端开发培训机构怎么样

小谷哥

加速文件传输协议如何工作

镭速

DevOps系列之 —— 持续规划与设计(三)敏捷项目管理的方法【Kanban 与 Scrum】

若尘

DevOps #DevOps 三周年连更

一文掌握 Go 文件的读取操作

陈明勇

Go golang 文件读取 三周年连更

大数据学习培训机构该怎么去选择

小谷哥

一文读懂域名注册

火山引擎边缘云

证书 域名 域名服务器

一文读懂封装

断墨寻径

#java 三周年征文

影驰 GeForce RTX 4070显卡正式开售!星曜 OC系列首发评测抢先看

Geek_2d6073

车企外卷:一个关于智能手机的“围城故事”

脑极体

手机 车企

达观助手AI写作下载安装教程及特色功能详解,速速收藏体验!

NLP资深玩家

devops|中小公司不要做研发效能度量

laofo

DevOps 研发效能 效能度量 DevOps工具链 研发效能度量

危中蕴机:Oi! Network展现出的勇气和决心

股市老人

Unity 之 转微信小游戏本地数据存储

陈言必行

Unity 三周年连更

HuggingGPT 强势来袭,LLM+ 专家模型,迈向更通用的AI

Zilliz

Zilliz Towhee ChatGPT LLM huggingface

vue3 +ts 如何安装封装axios

肥晨

Vue3 三周年连更

全球首个完全开源的指令跟随大模型;T5到GPT-4最全盘点

OneFlow

【坚果派-坚果】获取OpenHarmony 3.2 Release源码的两种方式

坚果

HarmonyOS OpenHarmony OpenHarmony3.2 三周年连更

openGauss社区三月运作报告

openGauss

zookeeper的节点加密方式及分布式锁实现过程

浅羽技术

三周年连更

对话ChatGPT:Prompt是普通人“魔法”吗?

Alter

云原生时代全链路观测体系构建

嘉为蓝鲸

一文读懂Annotation

老周聊架构

三周年连更

Swift在好大夫APP医患两端的打怪升级_AI&大模型_好大夫在线技术团队_InfoQ精选文章