AICon 上海站|日程100%上线,解锁Al未来! 了解详情
写点什么

【技研录】响应式编程在 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:59908

评论

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

阿里开源的“高并发设计笔记”就这水平!?我反正是跪着看完的

Java架构师迁哥

打破思维定式(七)

Changing Lin

5月日更

限流与Guava RateLimiter原理解析

千珏

Java 微服务 限流算法 Guava 令牌桶

HuskyLens人工智能摄像头

不脱发的程序猿

人工智能 智能硬件 AIOT HuskyLens 人工智能摄像头

怎么进大厂?166位Java工程师的大厂面试经验分享

北游学Java

Java 面试 大厂

我崩溃了!BTAJ面试有关散列(哈希)表的面试题详解,电子版已问世

欢喜学安卓

android 程序员 面试 移动开发

Apache Flink Meetup 北京站,1.13 新版本发布 x 互娱场景实践分享的开发者盛筵!

Apache Flink

大数据 flink

Spring Cloud Bus 消息总线介绍

阿里巴巴云原生

Java 微服务 云原生 中间件 数据格式

新思科技发现开源安全、许可证合规性和维护问题依然很普遍

InfoQ_434670063458

新思科技 OSSRA 开源安全

Fedora 34成哑巴了?

吴脑的键客

fedora

嵌入式程序调用函数的内部过程和机制

不脱发的程序猿

单片机 嵌入式程序 嵌入式设计

智慧党建三维云展厅可视化

一只数据鲸鱼

数据可视化 智慧党建 三维可视化

数据采集之js自定义采集

大数据技术指南

大数据

2021年5月国产数据库排行榜:“华为高斯模式”取得成功,阿里OPA持续攀升

墨天轮

数据库 dba tdsql TiDB Gauss DB

再次荣获最受观众喜爱奖

Serverless Devs

阿里云 云原生 cncf #Serverless

堪称完美!淘宝内部百亿级Java高并发系统架构设计PDF手册分享

Java架构追梦

Java 架构 高并发 淘宝网 亿级架构设计

云图说|不要小看不起眼的日志,“小日志,大作用”

华为云开发者联盟

运维 日志 云日志服务 安全监控审计

官宣:恭喜 ChaosBlade 项目进入 CNCF Sandbox

阿里巴巴云原生

容器 云原生 k8s 监控 Go 语言

论好文章和烂文章

阿里巴巴云原生

程序员 开发者 云原生 写作技巧 成长与思考

如何做一场高质量的分享

阿里巴巴云原生

深度学习 开发者 云原生 分享

数据库学习笔记

lenka

5月日更

Amazon Glue 版本 2.0 将作业启动时间缩短了 10 倍,现已全面开放!

亚马逊云科技 (Amazon Web Services)

CampusBulider(模模搭)学习笔记5:创建自定义建筑

ThingJS数字孪生引擎

大前端 可视化 3D 3D可视化 数字孪生

MapReduce排序以及序列化

五分钟学大数据

大数据 hadoop mapreduce

为啥你写的代码总是这么复杂?

华为云开发者联盟

软件 代码 代码注释 bug 复杂度

Linux C/C++ 学习路线总结!助我拿下腾讯offer

赖猫

后台开发 C/C++ Linux服务器开发

Amazon Route 53 Resolver 落地中国区,轻松玩转私有域名互访不是梦!| 新服务上线

亚马逊云科技 (Amazon Web Services)

更灵活的边缘云原生运维:OpenYurt 单元化部署新增 Patch 特性

阿里巴巴云原生

容器 运维 云原生 中间件 边缘计算

阿里开源的“SpringCloudAlibaba笔记”这么细节的吗?真秀!

Java架构师迁哥

STM32电源框图解析(VDD、VSS、VDDA、VSSA、VREF+、VREF-、VBAT等的区别)

不脱发的程序猿

嵌入式 stm32 单片机 电源框图解析

高性能JavaScriptの笔记(一)

空城机

JavaScript 性能优化 大前端 5月日更

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