理解Reactive编程思想

我们通过对比一个大家熟悉的例子,帮助大家熟悉Reactive Programming的编程思想。

从过滤一个常量数组开始

假设我们有一个包含数字1-10的字符串数组:

let stringArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10”]

如果我们要找出其中的偶数,并得到一个整数数组怎么做呢?

思路很简单,我们先把strArray变成一个整数数组,然后筛选出其中的偶数就可以了。借助函数式编程,我们可以很容易实现这个过程:

let even = stringArray.map { 
    Int($0)! 
}.filter { 
    $0 % 2 == 0 
}

得到结果后,我们把它打印到控制台上:

print(evenArray)

然后,Command + R编译执行,我们就能在控制台看到对应的结果了:

image

找到用户输入字符中的偶数

接下来,我们打开main.storyboard,从Object library里拖一个UITextField进来,并使用Xcode给它自动添加约束:

image

这次,如果我们希望自动获得用户的输入,并且只把用户输入的偶数打印在控制台上,怎么做呢?

最直接的想法当然是使用UITextField的一个delegate响应用户输入事件:

  1. 把输入的字符转换成整数;
  2. 筛选出可以被2整除的输入;

首先,我们给ViewController添加一个extension:

extension ViewController: 
    UITextFieldDelegate {
}

然后,实现textField(_: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String)方法。这个方法会在每次用户按下键盘,字母在屏幕上显示出来之前被调用:

public func textField(textField: UITextField,
    shouldChangeCharactersInRange range: NSRange,
    replacementString string: String) -> Bool {
        // 1\. Map input to Int
        if let n = Int(string) {
            // 2\. Filter even numbers
            if n % 2 == 0 {
                print(n)
            }
        }

        return true
}

实现的逻辑很简单,我们把用户每次的输入转换成一个整数,然后判断它是否可以被2整除。

完成之后,Command + R编译执行,输入不同的数字,我们就可以在控制台看到只有偶数被输出了:

image

为什么要举这两个例子呢?

常量数组是一个以索引为维度的串行结构

首先,对于常量数组来说,它是一个串行的,以索引为维度的内容序列,因此,我们对它的处理逻辑也是串行的。

我们先把数组中每个元素变成整数:

image

然后再逐个筛选中偶数;

image

对于得到的结果,我们使用print函数把它打印到了终端上。我们可以把print语句理解为这是我们对这个结果的某种”订阅”行为(一旦得到了某个偶数数组,就把它输出到控制台上)。

image

异步事件是一个以时间为维度的串行结构

接下来,对于UITextField来说,尽管用户输入是异步的,但如果我们以用户输入发生的时间作为维度,把所有已经发生的用户输入事件放在时间轴上,不难发现,我们也可以把得到的结果理解为是一个“常量数组”(因为过去已经发生的输入事件是不能被修改的)。

image

然后我们把这个数组中的元素先转换为整数,然后筛选出其中的偶数,就能得到我们想要的结果了。

image

因此,似乎存在一种可能性,我们可以定义一个以时间为维度的数组,它的元素是异步发生的事件。当事件发生时,我们就把它自动添加到这个数组里。然后,我们可以做两个事情,一方面,可以对添加进来的事件进行“二次加工”,筛选出符合我们要求的事件形态;另一方面,我们还可以添加对应事件的处理方法,这也就是某种形式的”订阅”。

image

这看似玄幻,实则它就是Reactive Programming的重要编程思想。理解它,也是我们使用Reactive Programming的最大挑战。

你可能感兴趣的:(理解Reactive编程思想)