译文-MVVM系列-RxSwift简介及Reactive Programming可以做的事情

本文翻译自RxSwift and the awesome things you can do with Reactive Programming — Part I(需要科学上网)

注:reactive programming,译者觉得是一个「专有名词」,同时也为了让读者更好理解其中含义,所以不翻译为「响应式编程」,直接用英语原文。

正文:

第一次接触reactive programming,我的表情是这样的:

First Impressions of reactive programming

第二、第三、第四次接触,也是心累。第一次参与到有reactive code的项目,简直是老鼠拉龟——无从下手。

我现在知道很多人第一次接触reactive programming也是和我一样的心情。而且很多人对reactive programming留下坏印象之后,再也不想去碰了,用起来太费劲儿。不过,另外一个事实是,在我所认识的人中,当他们切底弄明白reactive programming后,没有一个人后悔去用它。

网上已经有很多文章介绍reactive和RxSwift,也有很多教程教大家怎么处理Rx中的各种状况(文本后面会放一些相关链接)。所以这里不打算再写一篇教程去解释streams和observables的原理。我想提供一个简单、清晰、不涉及理论知识的总结,介绍用RxSwift可以做什么,以及为什么要用RxSwift。因为Rx涉及很多内容,所以打算用一个系列3篇文章来介绍。下面开始第一部分!

Part 1: Data Binding, control events and gesture recognizers

数据绑定,控制事件和手势识别

1. Data Binding

「Data binding/数据绑定」,这名词听起来有点故弄玄虚,不过其实很简单。假如你有一个app,需要用户在text field中输入他们的名字。用「"Hello, \(Name)"」来做问候。很简单的需求,对吧。在non-reactive app中,你需要在view controlelr中添加UITextFieldDelegate协议,并实现textFiledDidEndEding方法监测用户什么时候输入完他们的名字,然后添加一个label来显示输入的内容。

悲催的地方在于,用delegates来处理这个需求,相当繁琐。假如有多个text field呢?还需要添加判断,检查正在编辑的是哪个text field。如果客户要求label要和text field的输入保持同步更新呢?

在reactive中,此类需求可以用data binding来实现。简单来说,你需要绑定text field的数据到另一个UI对象(label)。利用RxSwift,没有比data binding更简单的了。在这个需求中,大概写成这个样子:

var nameField = UITextField()
var helloLabel = UILabel()
override func viewDidLoad() {
    nameField.rx.text.map { "Hello \($0)" }
                     .bindTo(helloLabel.rx.text)
}

让我们分析一下代码:首先,我们拿到text field的文本,然后映射(map)成我们需要赋值给label的内容。这里只是简单地在输入内容前加一个「Hello」,因为map是一个closure(闭包),所以可以用无名闭包参数(

1是第二个参数,依此类推)。然后我们将映射出来的文本绑定到label的text属性。这样就OK了。不用delegates、不用if,只需要几行简明扼要的代码。

可能你会觉得:看起来很美好,但是有多少app会有这样的需求?这里只能告诉你,不要囿于这个例子。能够将数据绑定到视图(views)是非常强大的功能,想想看:你可以根据天气的变化来改变视图的背景颜色,根据用户的位置导航到对应的商店的app……再次强调,本文不会太深入理论,不过这(数据绑定)就是其中的精髓。

2. Control Events and Gesture Recognizers

事件(events),如果你对这个概念不熟悉,基本上可以理解为:用户可以在app上执行的所有操作:tap, swipe, drag等等。当用户点击一个按钮,app会检测到这是UIControlEvent中的.touchUpInside。如果你用的是storyboards,在创建@IBAction的时候就会看到.touchUpInside。在这个例子中,不需要考虑按钮的点击事件。我曾经写过关于为什么我从来不用storyboards,如果你和我一样(不用storyboard),下面代码看起来就会非常熟悉:

var button = UIButton()
override func viewDidLoad() {
    button.addTarget(#selector(ViewController.loginUser), target: self, event: .touchUpInside
}
func loginUser() {
    // Implementation here
}

实不相瞒,我非常讨厌selectors,他们不够清晰,而且污染、分散了代码,还增加了出错的风险。而用Rx,则用如下方式添加按钮的action:

var button = UIButton()
var disposeBag = DisposeBag()
override func viewDidLoad() {
    button.rx.tap.subscribe { onNext _ in
        // Implementation here
    }.addDisposableTo(disposeBag)
}

别被disposeBag或者subscribe唬住,把他们看作是必要、固定的步骤就好了(你可以在文末的链接中找到更多相关资料)。

当没有control event的控件(比如UILabel、UIImage)被点击时,你需要执行某段代码,怎么办?非常悲催,只能用我非常讨厌的方法:添加gesture recognizers(手势识别)。

let label = UILabel()
override func viewDidLoad() {
    // Show example of gesture recognizers
    let gestureRecognizer = UITapGestureRecognizer(target: self, action: “handleTap:”)
    label.addGestureRecognizer(gestureRecognizer)
}
func handleTap() {
    // Your logic here
}

响应其他如swipe、drag、pan等手势也类似。如果希望响应多个手势,就需要分别创建、添加,这样不仅会产生很多重复代码,代码还容易混乱、出错。

你已经猜到了,Rx可以轻而易举地应对:

let label = UILabel()
let disposeBag = DisposeBag()
override func viewDidLoad() {
    label.rx.gesture(.tap).subscribe {onNext (gesture) in
        // Your logic here
    }.addDisposableTo(disposeBag)
}

如果需要处理多个手势,只需要这样处理:

let label = UILabel()
let disposeBag = DisposeBag()
override func viewDidLoad() {
    label.rx.gesture(.tap, .pan, .swipeUp).subscribe { onNext (gesture) in
        switch gesture {
        case .tap: // Do something
        case .pan: // Do something
        case .swipeUp: // Do something 
        default: break       
        }        
    }.addDisposableTo(disposeBag)
}

这些在RxGesture中都有提供。

今天到此结束,但是请继续关注本系列其他文章。如有疑问或建议,评论区,不吝赐教。

Resources

ReactiveX/RxSwift

Functional Reactive Awesomeness With Swift

Reactive Swift

The-introduction-to-RxSwift-you-have-been-missing

RxSwift by Examples 1 – The Basics

I create iOS apps - is RxSwift for me?

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1hsnfn0jgsjiu

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券