Upload
others
View
20
Download
0
Embed Size (px)
Citation preview
探究晌应式编程在 iOS 开发中的优
势iDev
前青 K
自我介绍
• 宋旭陶/前青 K
• SwiftGG 真灌水成员
• ENJOY iOS 工程师
• RxSwift & FRP 爱好者
今天的目的
• 让没有尝试过 RxSwift 的您产生兴趣
• 让已经有所尝试的您有新的灵感
以 RxSwift 为例
摘要
• 解决 Callback Hell
• RxSwift 原理
• 非网络请求形式的异步实践
Callback Hell
回调地狱Alamofire.request(.POST, "login", parameters: ["username": "max", "password": "insanity"])
.responseJSON(completionHandler: { (firedResponse) -> Void in Alamofire.request(.GET, "myUserInfo" + firedResponse.result.value)
.responseJSON(completionHandler: { myUserInfoResponse in Alamofire.request(.GET, "friendList" +
myUserInfoResponse.result.value).responseJSON(completionHandler: { friendListResponse
inAlamofire.request(.GET, "blockedUsers" +
friendListResponse.result.value).responseJSON(completionHandler: {
})})
})})
使用 RxSwift 解决回调地狱
Alamofire.request(.POST, "login", parameters: ["username": "max", "password":
"insanity"]).flatMap { firedResponse in
Alamofire.request(.GET, "myUserInfo" + firedResponse.result.value)}.flatMap { myUserInfoResponse in
Alamofire.request(.GET, "friendList" + myUserInfoResponse.result.value)}.flatMap { friendListResponse in
Alamofire.request(.GET, "blockedUsers" + friendListResponse.result.value)}
只用 RxSwift 解决
网络回调吗?
RxSwift 基本原理
以 Todo 为例
一个数组的添加
+
Todo 4 Todo 1 Todo 2 Todo 3
Todo 1 Todo 2 Todo 33
3
Todo 1 Todo 3Todo 2
Todo 4
0)at:todoList.insert("Todo"Todo 2", "Todo 3"]1",
4",var todoList = ["Todo
真实场景
tableView.beginUpdates()tableView.insertRows(at: [IndexPath(row: 0, section: 0)],
with: .automatic) tableView.endUpdates()
维护数据
0)at:todoList.insert("Todo"Todo 2", "Todo 3"]1",
4",var todoList = ["Todo
维护视图手动
自动维护/晌应式/观察者模式
数据驱动
tableView.beginUpdates()tableView.insertRows(at: [IndexPath(row: 0, section: 0)],
with: .automatic) tableView.endUpdates()
夷?数据变了,增加了 “Todo 4”我对应做一些更新
我 (todoList) 有变动
我在顶部增加了 “ Todo 4”
0)at:todoList.insert("Todo"Todo 2", "Todo 3"]1",
4",var todoList = ["Todo 数据
视图
自动维护/晌应式/观察者模式
数据
订阅
通知
我 (todoList) 有变动
我在顶部增加了 “ Todo 4”
数据视图视图
回到真实场景
ๅๅๅๅ
ᅩ ๅๅفᑻๅๅڊAddๅ ڋ ๅๅๅๅᅩ ๅๅڋ
用户行为
用户触发才进行下一步
ๅๅๅๅ
ᅩ ๅڋ ๅ
ᅩ Add ڋ ๅفๅๅๅڊᑻๅๅๅๅๅ
等待用户行为等待用户行为 = 等待网络回调
• 回调触发时间未知
• 可以采用 Closure / delegate / target-action
利用原生 API 实践
代码很容易变得很乱 易读性很差
ๅๅๅๅ
ᅩ ๅڋ ๅ
ᅩ Add ڋ
Target-action
ๅفๅๅๅڊᑻๅๅๅๅๅ
Closure
ObservableObservable Observable Observable
Observable
Observable
ๅๅๅๅ
ᅩ ๅๅفᑻๅๅڊAddๅ ڋ ๅๅๅๅᅩ ๅๅڋ
一切都是“同步”的
(Click Add).(Show Alert).(Input Text).(Click Ensure).(Update Database).(Update View)
一切都是“同步”的
addBarButtonItem.rx
. .tap
. .flatMap(showTextField).map { [$0] }. .scan([String](), accumulator: +)
. .map { [TodoSectionModel(model: "", items: $0)] }.bindTo(tableView.rx.items(dataSource: dataSource))
.(Update View)
(Click Add) (Show Alert) (Input Text) (Click Ensure)(Update Database)
晌应式
+
数据
订阅 ᅩ Add ڋ
ᅩ ๅๅๅๅๅๅڋ
ๅفๅๅๅڊᑻๅ
ๅๅๅๅ
视图
填写信息对“如何在 iOS 中实现一个
可 展开的 Table View”的实践
http://swift.gg/2015/12/03/expandable-table-view/
http://swift.gg/
。no,anQK ==..Expandable )Io;anOK
R u n , n g h p andab l e
E8
2’响wController.swat ) 囚由 tew 肺,Sel刷刷ω
Low 2、Z KB/SZero KB/s
u
e
,
c
o
m
.
.
.
t
v
e
a
d
<
s
e
r
i
a
)
e
d
_
f
a
t
o
l
E
r
r
o
r
M
e
s
s
a
g
e
.
.
'""崎eIObloVio叫UITo•.. ewe。ntroller.tab!eVle.••N始w seleetRowAtlnd-,
叭;
ew _US8'Selec
1ROW.. 它ACommOelerr回Bl...
,AtterCAFlushAnd民un
::omm,
协
<
a
n
d
l
e
r
,且
P
_
I
S
_
C
A
L
L
I
N
G
”pO Obs0< ers IL。。pRun 甜 RunSpecif;c tRunM。dell
1
c
a
t
,
o
n
阳,1
)
:a11 nMa,n
。
凶
刷刷刷rtetch thread (...
•aindex阳h
阳阳问
时 2
indices
Expandab e ) 0 Thread ’ 〉囚 1View 臼ntroller.t 甜甜ew(UITabl制ew,d1dSe 协 c1RowAt ,lndexPath) 叫}
•FJ 剧’ 叫叩叫b叫wC
帆川崎•>
Ox000000013SdO
e3cO
IInde 呻ITappcdRow
•阳I12咀酬 f_eace咀盒 ,11....
立阻固 lAU10 C⑥
Outo
⑤
idal
el pd kve
叫
Iud n eorA Ot rproen 13 8tm
wan zyAp lp
2d2曲”-
E 93n
u
-
e’ ”130a8问
[wellbdaa
a
叮pv8ux@ OE
-
ef ae
7n
。
@
y9818 18d9teu B P
et8o
ece8
口7nepea
aouAx e5 8
@n5nU
LZ
3 nv工 P
。
er a$ 07 r
r
@
四”· }
r
-n·u e
-u-au6 L。-
t xvo o
问
【 f2w
奇怪的 Bu
查找父级单元格
理解错了函数
硬编码
复杂的 if else
如何优雅的展开 Cell
• Dif 处理
• 判断那些是新增、删除数据
• 调用相关 API
• 应用晌应式
建立 SubItems
没有显示已经输入的内容
绑定
(firstName + lastName) => title
Observable.combineLatest(
firstName, lastName
) { $0 + " " + $1 }.bindTo(title)
textFieldCell.rx.text lastName
textFieldCell.rx.text firstName
(title => textLabel.rx.text)
date.map(format) => title
date.asObservable().map(DateFormatter().config.longStyle.string).bindTo(title)
(datePickerCell.rx.date date)
(title => textLabel.rx.text)
isMarried.map(format) => title
isMarried.asObservable().map { $0 ? "Married" : "Married" }.bindTo(title)
(switchCell.rx.isOn isOn)
冥他例子
• 书籍目录
• Apple 计时器
结合 Redux ?
总结
• RxSwift = Observable + LINQ• RxSwift 是数据/事件驱动框架• RxSwift 可以解决各种异步问题
目关内窑• RxSwift vs PromiseKit
• DianQK/rx-sample-code
• DianQK/rx-redux-sample-code
• RxDataSources
• 如何在 iOS 中实现一个可展开的 Table View
• devxoul/RxTodo
提问?
• Weibo: 前青 K• Twitter: Songxut
mailto:[email protected]