写点什么

【技研录】响应式编程在 Swift 中的使用

  • 2023-11-24
    北京
  • 本文字数:3225 字

    阅读完需:约 11 分钟

【技研录】响应式编程在 Swift 中的使用

写作思考:

响应式编程(Reactive Programming)是一种编程范式,它以数据流和变化传递为核心概念,可以简化代码结构,提高程序的可读性和可维护性。在 Swift 中,响应式编程已经得到了广泛的应用,并成为了一些流行框架的基础,开发者可以通过框架提供的操作符对数据流进行各种变换。目前在众安科技经代 App 中全面使用,整体代码逻辑更加清晰,开发效率上得到了明显的提升。


目录

1.什么是响应式编程

2.函数式 Swift

3.MVVM

4.MVVM 与响应式结合

5.总结


一.什么是响应式编程

 

Wiki 上的解释: Reactive programming 是一种面向数据串流和变化传播的声明式编程范式。

iOS 客户端的原生开发使用 Objective-C 和 Swift 开发,使用 Objective-C 的时候注重面向对象编程,大多数都是使用命令式的编程,Swift 更注重面向协议编程、函数式编程。

 

做过 iOS 客户端的同学一定了解过 KVO 这个内置的 Api,KVO 可以帮助我们将属性的变更和变更后的处理分开,简单的理解就是一个对象的属性改变后,另外一连串对象的属性都随之发生改变。KVO 的写法和使用上比较复杂,而且只支持 NSObject ,局限性太大。 

 

Apple 在推出 Swift 之后,响应式的编程基于数据流的理念,异步的处理事件和函数式编程能很好的结合,ReactiveX 推出了响应式的库 RxSwift,WWDC 2019 上 Apple 公布了声明式全新界面框架 SwiftUI,以及配套的响应式编程框架 Combine,Combine 只支持 iOS13 以上的系统,毕竟属于原生的框架,在性能上要稍微强于 RxSwift,根据支持的版本差异开发者可以自行选择。 

 

最新推出 Rx 的微软对响应式编程的解释是 Rx = Observables + LINQ + Schedulers,通俗一些的解释就是面向异步数据流编程。数据流可以有多种形式,比如读取一个文件、进行一个网络请求、用户出发的行为等等,都可以认为是一种数据流,当然一个变量也可以认为是一种数据流。

                                   

二.函数式 Swift

 

函数式编程中的函数这个词不是指计算机中的函数,而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如 sqrt(x) 函数计算 x 的平方根,只要 x 不变,不论什么时候调用,调用几次,值都是不变的。


1. 一等公民函数与高阶函数


在函数式编程中,函数是一等公民,不再把函数想象成一个处理过程,而是把它当作一个对象或者变量来对待。

 

 

在 Swift 中可以很方便的把一个函数赋值给一个常量,这个在 Objective-C 中是做不到的。所谓的高阶函数,指可以将其他函数作为参数或者返回结果的函数,Swift 中的函数都是高阶函数,系统库提供了(map,fillter,reduce 等)

 


通过函数这个“管道”,数据从一头经过“管道”到另一头,就得到了想要的数据。

 

2.柯里化

 

Swift 里可以将方法进行柯里化 (Currying),这是也就是把接受多个参数的方法进行一些变形,使其更加灵活的方法。函数式的编程思想贯穿于 Swift 中,而函数的柯里化正是这门语言函数式特点的重要表现。

 


柯里化是一种量产相似方法的好办法,可以通过柯里化一个方法模板来避免写出很多重复代码,也方便了今后维护。

 

3.闭包

 

闭包是一个会对它内部引用的所有变量进行隐式绑定的函数。也可以说,闭包是由函数和与其相关的引用环境组合而成的实体。函数实际上是一种特殊的闭包,你可以使用{ }来创建一个匿名闭包。使用 in 来分割参数和返回类型。

 


上面 map 函数遍历了数组,用闭包处理了所有元素,并返回了一个处理过的新数组。

那么遵循以上特性,一个好的 Swift 函数式程序会具有一下特质:

 

  ● 模块化:相较于把程序认为是一系列赋值和方法调用,函数式开发者更倾向于强调每个程序都能够被反复分解为越来越小的模块单元,而所有这些块可以通过函数装配起来,以定义一个完整的程序。

 

  ● 对可变状态的谨慎处理:面向对象编程专注于类和对象的设计,每个类和对象都有它们自己的封装状态。然而,函数式编程强调基于值编程的重要性,这能使我们免受可变状态或其他一些副作用的困扰。通过避免可变状态,函数式程序比其对应的命令式或者面向对象的程序更容易组合。

 

  ● 类型:一个设计良好的函数式程序在使用类型时应该相当谨慎。精心选择你的数据和函数的类型,将会有助于构建你的代码,这比其他东西都重要。Swift 有一个强大的类型系统,使用得当的话,它能够让你的代码更加安全和健壮。

 

在实际开发过程中,我们遵循函数式思维去编码,可以很容易地使用 Swift 写出函数式风格的代码,为我们带来以下好处:

 

1. 方便组件解耦

2. 单元测试和调试都更容易

3. 更方便的代码管理

 

三.MVVM

 

MVVM 可以说几乎就是一个 MVC,不过通过 View Model 层来将数据和视图进行绑定。熟悉 iOS 开发的小伙伴都知道,iOS 的 Cocoa 框架都是基于 MVC 设计的,关于 MVC,我们可以看下斯坦福的 CS193p Paul 这张经典图



MVC 本身的概念相当简单,同时它也给了开发者很大的自由度。Massive View Controller 往往就是利用了这个自由度,“随意”地将逻辑放在 Controller 层所造成的后果,此时的 M 不是 Model 已经变成了 Massive。



使用 MVVM 之后可以大大减轻 View Controller 职责,简化后的各个模块分工更加明确,更加方便集成和开发。我们在使用的时候主要遵循一下几个事项:

    ●  ViewController 尽量不涉及业务逻辑,让 ViewModel 去做这些事情,此时的 ViewModel 实际上的职责是 Controller

    ● ViewModel 绝对不能包含视图 View(UIKit.h),不然就跟 View 产生了耦合,不方便复用和测试

    ● iewModel 避免过于臃肿,否则重蹈 Controller 的覆辙,变得难以维护

 

MVVM 是 MVC 的升级版,完全兼容当前的 MVC 架构,MVVM 虽然促进了 UI 代码与业务逻辑的分离,一定程度上减轻了 ViewController 的臃肿度,但是 View 和 ViewModel 之间的数据绑定使得 MVVM 变得复杂和难用了,如果我们不能更好的驾驭两者之间的数据绑定,同样会造成 Controller 代码过于复杂,代码逻辑不易维护的问题。


四.MVVM 与响应式结合

 

上面介绍完 MVVM,那应该怎么和响应式结合起来呢?我们先来看下在 iOS 中是怎么进行状态更新的

  ● Target-Action

  ● Delegate

  ● KVO

  ● Notifications

  ● Callback

 

多种回调方式,适用规则、适用场景都不相同,这增加了开发、维护的难度。如果有一种方式可以把状态更新做到统一,那就可以大大提高开发效率,这里就要提到 Rx 了,它把状态变更都转化成流,MVVM 中的 ViewModel 和 Rx 相结合这样就可以做到响应式了。

 

先来看个例子,一个登录界面



产品经理说了需求:

  ● 账号是手机号 11 位

  ● 密码大于 6 位

  ● 当满足上面条件,点击统一条款,下面登录按钮为可点击状态否则不可点击

 

按照一般思路,2 个输入框对应的是 2 个 UITextField 控件,还有 2 个 UIButton 控件对应单选按钮和登录按钮,我们需要实现这个需求就要做到以下:

  1. 在 UITextField 的 Delegate 里面去监听输入的内容

  2. 在 UIButton 的 Action 方法里面监听隐私条款是否点击

  3. 2 个输入框和 1 个隐私按钮,这 3 个控件每次更新状态都要去看另外 2 个是否满足登录按钮可点击

 

可以见到这样一个简单的需求,在代码实现上要处理的逻辑很多,而且都是分散的,那么我们能不能只罗列条件,然后把这些条件扔给一个条件处理的机制,这个机制就能帮我们正确的处理这些关系?

 

 

伪代码如下:


 

实际处理中会把这些逻辑放到 ViewModel,这样就把 RxSwift,函数式,MVVM 结合起来,达到了响应式编程的样子。

 

五.总结

 

Swift 从 2014 年发布,到 iOS13 推出的响应式 Combine,开源也一直推动语言的发展,可能未来 1 天苹果会抛弃原来 Cocoa 框架实现,利用新语言的特性也不是不可能。任何架构和技术都不能满足所有的工程需求,能够使用简单的架构来搭建复杂的工程,制作出让其他开发者可以轻松理解的软件,避免高额的后续维护成本,让软件可持续发展并长期活跃,应该是每个开发者在构建软件是必须考虑的事情。

 

参考资料:

 

  1. 关于 MVC 的一个常见的误用

  2. iOS 下的响应式编程

2023-11-24 16:59808

评论

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

大厂B端/G端数据可视化项目如何做设计评审

京东科技开发者

25更敢为 | TATA木门25周年庆典盛大启幕 探索家居品质生活新静界

Geek_2d6073

你还在用工单系统的思维建设ITSM吗?

嘉为蓝鲸

ITSM 运维管理 平台化

一图解锁 | 运维管理到工具体系的建设逻辑

嘉为蓝鲸

运维管理 运维工具

主流国产数据库的HTAP实现,TiDB实现的最早并应用的最深

TiDB 社区干货传送门

数据库架构设计

TiDB Server 的优雅下线

TiDB 社区干货传送门

数据库连接

听说京东618裁员没?上午还在赶需求,下午就开会通知被裁了~

王中阳Go

Go 面试 微服务 后端 Go进阶

看不懂正则表达式?试试可视化工具吧!

京东科技开发者

TiDB 的平面文件与数据体积

TiDB 社区干货传送门

管理与运维

win版Iperius Backup Full (数据备份工具) v8.1.7 中文激活版

iMac小白

2024年安全生产月资料合集,抓紧保存!

草料二维码

资料分享 安全生产月

9 个适用于小型企业的顶级API管理解决方案

幂简集成

API API接口管理 API接口工具 API管理

抖音商品API接口:开启电商自动化和数据洞察之门

Noah

AI功能探测,TiDB Vector对比PG Vector

TiDB 社区干货传送门

版本测评 性能测评 7.x 实践

一键自动化博客发布工具,用过的人都说好(公众号篇)

程序那些事

工具 程序那些事 自动发布

京东面试:SpringBoot同时可以处理多少请求?

王磊

数字孪生智慧工厂解决方案——打造绿色、透明重卡超级工厂

图扑物联

工业物联网 组态软件 数字孪生 web组态 智慧工厂

rbenv:Ruby 多版本管理利器

不在线第一只蜗牛

ruby 后端 项目开发

长江云 IPTV 融合业务 0 改造平滑迁移上云,《面向 AIGC 的数智广电新质生产力构建白皮书》开放下载

Baidu AICLOUD

vmware 专有云 IPTV

深入解析:Netty 与 Dubbo 的关系与应用

Liam

程序员 dubbo 后端 Netty 分布式系统

大模型在蓝鲸运维体系应用——蓝鲸运维开发智能助手

嘉为蓝鲸

运维 大模型 运维管理

TiDB 黑科技工具集之 dbgen(造数工具)

TiDB 社区干货传送门

实践案例

鸿蒙HarmonyOS实战-Stage模型(应用上下文Context)

EquatorCoco

鸿蒙 HarmonyOS

牛马真的沉默了,入职第一天就干活

秃头小帅oi

ITSM新用法揭秘:构建科技公司售后服务管理体系

嘉为蓝鲸

运维 ITSM 流程管理

TiKV的Raft逻辑梳理总结

TiDB 社区干货传送门

TiKV 底层架构

小冰携手火山引擎,让 AI 从崭露头角到落地生根

新消费日报

云+AI,火山引擎助力泛互联网行业创新和增长

新消费日报

面向AI的开发:从大模型(LLM)、检索增强生成(RAG)到智能体(Agent)的应用

京东科技开发者

2024深圳国际数字能源展览会

AIOTE智博会

能源展 数字能源展 深圳能源展

TiDB 如何利用 Copilot 优化数据库操作,提升用户体验与内部效率?

TiDB 社区干货传送门

【技研录】响应式编程在 Swift 中的使用_云计算_众安保险_InfoQ精选文章