2021-01-27

Combine之简述

用Apple的话说,Combine是:

a declarative Swift API for processing values over time

这句话包含了Combine的3大核心:

  • declarative表示Combine的语法是声明式的
  • values表示Combine处理的数据不是单独的,是多个且复杂的
  • over time表示要处理的数据带有时间影响,也就是带有时间序列的事件流

总结一下,Combine就是专门用于处理事件流的声明式编程框架。

这里需要解释下为何是事件流而不是数据流,比如有这样一个场景:

  1. 当用户输入一个关键词
  2. 去重
  3. 发送网络请求
  4. 错误校验
  5. 数据解析

上边就是所谓的5个事件,每个事件都有各自的输入和输出。如果我们把他们链接在一起,就组成了一条数据流通管道,简称数据流。我们看下代码是怎样的?

enum NetworkError: Error {
    case invalidResponse
}

struct Student: Codable {
    let name: String
    let age: Int
}

let publisher = PassthroughSubject()

cancellable = publisher
    .removeDuplicates()
    .flatMap { value in
        return URLSession.shared.dataTaskPublisher(for: URL(string: "https://xxx.com?name=\(value)")!)
    }
    .tryMap { (data, response) -> Data in
        guard let httpResp = response as? HTTPURLResponse, httpResp.statusCode == 200 else {
            throw NetworkError.invalidResponse
        }
        return data
    }
    .decode(type: Student.self, decoder: JSONDecoder())
    .catch { _ in
        Just(Student(name: "", age: 0))
    }
    .sink(receiveCompletion: {
        print($0)
    }, receiveValue: {
        print($0)
    })

publisher.send("张三")
复制代码

什么是Functional reactive programming(函数响应式编程)

image.png

网络上已经有很多文章详细地介绍了函数响应式编程,但读下来还是令人产生很多疑惑,在本小节,我尝试对函数响应式编程做一些简单的介绍。

就像上图所示一样,要理解函数响应式编程就需要分别理解函数式编程和响应式编程

函数式编程非常好理解,我们从下边2个重要概念入手:

  • 予以函数数学特性
  • 予以函数一等公民身份

那么什么叫予以函数数学特性呢?很简单,凡是带有数学特性的东西都必须是逻辑严谨的,计算安全的。在函数式编程的世界中,函数绝对不能修改变量的状态,一个输入数据必定产生一个固定的输出数据。

image.png

当一个函数是安全的时候,它就可以参与到数据的运算和传递。因此,函数身份提升到一等公民,它既可以作为另一个函数的参数,也可以作为另一个函数的返回值。

可以在这里了解到Swift函数式编程的详细内容:一文读懂Swift函数式编程

来到响应式编程就没那么好理解了,很多开发的同学习惯了写函数,不一定习惯编写响应式的代码。所谓的响应实质上就暗含了Stream的概念。

这时候,输入数据就不再是死数据,而是随着时间而不断变化,不同的输入会产生不同的输出,因此,我们就需要对这些输出做出一定的响应。

举个例子:

var a = 1
var b = 2

c = a + b

/// c == 3

a = 2
复制代码

在上边的代码中,我们把a和b想象成输入数据,把c想象成输出数据,当我改变了a的值后,输出数据c并没有改变,这就不是响应式的。

响应式编程思想解决的问题就是数据的流动问题,尤其当数据是异步流动的情况,更复杂一点是多个数据的异步流动。

当我们把函数式编程和响应式编程组合起来就是函数响应式编程。像下边这张图一样:

image.png

把数据的处理过程想象成由多个函数组成的黑盒子,

image.png

也可以想象成水流管道,我们只需要提前布置好合适的管道,就等待数据输入,然后做出响应。

image.png

什么时候用Combine?

SwiftUI中Views刷新机制的核心是Source of Truth,即Views展示的内容完全依赖其状态,状态改变,UI也跟着改变。虽然SwiftUI和Combine是天然的同盟关系,在其他的框架中,仍然可以使用Combine。

如果以最宏观的视角看问题,当遇到下边2个问题时,就可以考虑使用Combine:

  • 异步任务
  • 数据会随时间而改变

在平时的开发中,异步任务非常之多,Combine天然就是处理异步任务的好手,在后边的文章中会有这方面详细的讲解。

总结

Combine是iOS13引进的,因此要想使用Combine开发程序,系统版本最低要求为iOS13。UIKit和SwiftUI都可以使用。尤其是SwiftUI,有了Combine这一利器之后,真正的做到了逻辑和UI分离。

你可能感兴趣的:(2021-01-27)