RxSwift学习之旅 - Action

简介

Action是observable的一个抽象库,它定义了一个动作,传入输入的事件,然后对事件进行处理,返回处理结果。它有如下特点:

  • 只有enabled的时候才会执行,可以传入enabledIf参数
  • 同时只能执行一个,下次input必须等上次的action执行完
  • 可以分别处理错误和next

创建Action

Action被定义为一个类Action<Input, Element>,Input是输入的元素,ElementAction处理完之后返回的元素。

一个简单的例子,没有输入也没有输出如下:

1
2
3
4
let buttonAction: Action<Void, Void> = Action {
print("Doing some work")
return Observable.empty()
}

或者传入用户名密码,返回登录结果:

1
2
3
4
5
let loginAction: Action<(String,String), Bool> = Action{
(username, password) in
print("\(username) \(password)")
return Observable.just(true)
}

连接Button

buttonAction怎么使用,你可以把它和button的点击绑定起来:

1
button.rx.action = buttonAction

每次点击按钮Action都会执行,如果上一次的点击Action没有完成的话,这个的点击将会无效。

设置为nil去取消绑定

1
button.rx.action = nil

用户登录

我们可以把输入的账号密码绑定到上面的loginAction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let usernameAndPassword = Observable.combineLatest(username.rx.text.orEmpty, password.rx.text.orEmpty)
login.rx.tap.asObservable()
.withLatestFrom(usernameAndPassword)
.bindTo(loginAction.inputs)
.disposed(by: disposeBag)
loginAction.elements
.filter{ $0 }
.subscribe(
onNext:{
_ in
print("login ok!")
}
)
.disposed(by: disposeBag)
loginAction.errors
.subscribe(
onError:{
error in
print("error")
}
)
.disposed(by: disposeBag)

输入的账号密码绑定到loginAction.inputs,然后订阅loginAction的结果。

cell点击

可以给每个UITableViewCell里面的button去绑定一个Action

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let items = Observable.just(
(0...20).map{ "\($0)" }
)
items.bindTo(tableview.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)){
(row, elememt, cell) in
let title = cell.viewWithTag(100) as! UILabel
title.text = elememt
var button = cell.viewWithTag(101) as! UIButton
button.rx.action = CocoaAction {
print("to do something \(elememt)")
return .empty()
}
}.disposed(by: disposeBag)

execute

除了绑定输入以外,还可以主动去执行Action

1
2
3
4
5
loginAction.execute(("admin","password"))
.subscribe{
print($0)
}
.disposed(by: disposeBag)

通过execute传入账号密码,然后执行Action并订阅结果。

enabledIf

只有当条件满足的时候Action才会执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let usernameCount = username.rx.text
.orEmpty
.asObservable()
.map{
$0.characters.count > 6
}
let validateUsername:Action<String, Bool> = Action(enabledIf: usernameCount, workFactory: { input in
print("username validating.....")
return Observable.just(true)
})
username.rx.controlEvent(.editingDidEnd)
.subscribe(
onNext:{
[unowned self] _ in
validateUsername.execute(self.username.text ?? "")
}
)
.disposed(by: disposeBag)

UIAlertAction

UIAlertAction绑定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
validateUsername.elements
.observeOn(MainScheduler.instance)
.subscribe{
[unowned self] _ in
print("username validate ok")
let alertController = UIAlertController(title: "validate", message: "username validate is ok!", preferredStyle: .alert)
var ok = UIAlertAction.Action("OK", style: .default)
ok.rx.action = CocoaAction {
print("Alert's OK button was pressed")
return .empty()
}
alertController.addAction(ok)
self.present(alertController, animated: true, completion: nil)
}
.disposed(by: disposeBag)

总结

Action可以用来定一个动作触发后的一个行为,也可以绑定多个动态到同一个Action,和MVVM结合的时候变得尤为合适。

代码见github:

RxSwiftAction

AloneMonkey wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!