Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
RxSwift
(github.com/devxoul)
• StyleShare Inc.
• SW Maestro 2
• RxSwift
RxSwift?
RxSwift = ReactiveX + Swift
RxSwift = ReactiveX + Swift
RxSwift = ReactiveX + Swift
?
RxSwift = ReactiveX + Swift
Re + ActiveX
RxSwift = ReactiveX + Swift
Reactive + Extension
RxSwift = ReactiveX + Swift
RxSwift = ReactiveX + Swift
?
a = 10
b = a * 2
a = 10
b = a * 2
print(b)
a = 10
b = a * 2
print(b) // 20
a = 10
b = a * 2
print(b) // 20
a = 30
a = 10
b = a * 2
print(b) // 20
a = 30
print(b)
a = 10
b = a * 2
print(b) // 20
a = 30
print(b) // 20
a = 10
b = a * 2
print(b) // 20
a = 30
print(b) // 20 60
ReactiveX
Observer
Pattern
Iterator
Pattern
Functional
Programming
ReactiveX
Observer
Pattern
Iterator
Pattern
Functional
Programming
Observable
Observer
Observable
Observer
observe
Observable
Observer
observe notify
Observable
ObserverObserver Observer
ReactiveX
Observer
Pattern
Iterator
Pattern
Functional
Programming
Iterator next()
hasNext()
Iterator next()
hasNext()
10 20 30 40
Iterator next()
hasNext()
10 20 30 40
Iterator next()
hasNext()
10 20 30 40
iterator.next()
Iterator next()
hasNext()
10 20 30 40
iterator.next() // 10
Iterator next()
hasNext()
10 20 30 40
Iterator next()
hasNext()
10 20 30 40
iterator.next()
Iterator next()
hasNext()
10 20 30 40
iterator.next() // 20
Iterator next()
hasNext()
10 20 30 40
Iterator next()
hasNext()
10 20 30 40
iterator.next()
Iterator next()
hasNext()
10 20 30 40
iterator.next() // 30
Iterator next()
hasNext()
10 20 30 40
Iterator next()
hasNext()
10 20 30 40
iterator.next()
Iterator next()
hasNext()
10 20 30 40
iterator.next() // 40
Iterator next()
hasNext()
10 20 30 40
Iterator next()
hasNext()
10 20 30 40
iterator.hasNext() // false
ReactiveX
Observer
Pattern
Iterator
Pattern
Functional
Programming
•
• ,
•
•
• ...
higher-order fuction
pure fuction
•
•
• ...
higher-order fuction
pure fuction
1.
2.
var array = [2, 6, 3, 1, 7]
array.sort(by: { a, b in
return a < b
})
var array = [2, 6, 3, 1, 7]
array.sort(by: { a, b in
return a < b
})
var array = [2, 6, 3, 1, 7]
array.sort(by: { a, b in
return a < b
})
•
•
• ...
higher-order fuction
pure fuction
•
•
•
•
( , , I/O )
•
•
var rate = 1130
func krw(usd: Int) -> Int {
return usd * rate
}
var rate = 1130
func krw(usd: Int) -> Int {
return usd * rate
}
krw(usd: 2) // 2260
krw(usd: 3) // 3390
var rate = 1130
func krw(usd: Int) -> Int {
return usd * rate
}
rate = 1140
krw(usd: 2) // 2260
krw(usd: 3) // 3390
var rate = 1130
func krw(usd: Int) -> Int {
return usd * rate
}
rate = 1140
krw(usd: 2) // 2260 2280
krw(usd: 3) // 3390 3...
var rate = 1130
func krw(usd: Int) -> Int {
return usd * rate
}
rate = 1140
krw(usd: 2) // 2260 2280
krw(usd: 3) // 3390 3...
var rate = 1130
func krw(usd: Int) -> Int {
return usd * rate
}
rate = 1140
krw(usd: 2) // 2260 2280
krw(usd: 3) // 3390 3...
func krw(usd: Int) -> Int {
return usd * rate
}
func krw(usd: Int ) -> Int {
return usd * rate
}
func krw(usd: Int, rate: Int) -> Int {
return usd * rate
}
func krw(usd: Int, rate: Int) -> Int {
return usd * rate
}
ReactiveX
Observable
Pattern
Iterator
Pattern
Functional
Programming
a 10
b a * 2
a 10
b 20
a
b
10 20 30 40a
20 40 60 80b
10 20 30 40a
20 40 60 80b
10 20 30 40a
20 40 60 80b
map(x => x * 2)
10 20 30 40a
20 40 60 80b
map(x => x * 2)
Marble Diagrams
20 40 60 80b
map(x => x * 2)
Observable.from([10, 20, 30, 40])
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value) // 20
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value) // 40
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value) // 60
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value)
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value) // 80
})
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value) // 80
})
Observable
Observable.from([10, 20, 30, 40])
.map { $0 * 2 }
.subscribe(onNext: { value in
print(value) // 80
})
Observer
Password
(4 )
1
(4 )
. ❌
12
(4 )
. ❌
123
(4 )
. ❌
1234
(4 )
. 👍
"1"
"1"
map(str => str.length >= 4)
"1"
map(str => str.length >= 4)
false
"1"
false
map(str => str.length >= 4)
map(valid => getMessage(valid))
"1"
false
map(str => str.length >= 4)
"❌ "
map(valid => getMessage(valid))
"1" "12"
false
map(str => str.length >= 4)
"❌ "
map(valid => getMessage(valid))
"1" "12"
false false
map(str => str.length >= 4)
"❌ "
map(valid => getMessage(valid))
"1" "12"
false false
map(str => str.length >= 4)
"❌ " "❌ "
map(valid => getMessage(valid))
"1" "12" "123"
false false
map(str => str.length >= 4)
"❌ " "❌ "
map(valid => getMessage(valid))
"1" "12" "123"
false false false
map(str => str.length >= 4)
"❌ " "❌ "
map(valid => getMessage(valid))
"1" "12" "123"
false false false
map(str => str.length >= 4)
"❌ " "❌ " "❌ "
map(valid => getMessage(valid))
"1" "12" "123" "1234"
false false false
map(str => str.length >= 4)
"❌ " "❌ " "❌ "
map(valid => getMessage(valid))
"1" "12" "123" "1234"
false false false true
map(str => str.length >= 4)
"❌ " "❌ " "❌ "
map(valid => getMessage(valid))
false false false true
map(str => str.length >= 4)
map(valid => getMessage(valid))
"1" "12" "123" "1234"
"❌ " "❌ " "❌ " "👍"
passwordField.rx.text.orEmpty
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
}
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
passwordField.rx.text.orEmpty
.map { $0.characters.count >= 4 }
.map { isValid in
if isValid {
return " . 👍"
} else {
retu...
: Observable<String>
: Observable<Int>
: Observable<Void>
: Observable<CGPoint>
...
Observable
"1" "12" "123" "1234"
"1"
"1"
"1" "12"
"1" "12"
"1" "12" "123"
"1" "12" "123"
"1" "12" "123" "1234"
Nickname
. ❌
. ❌
. 👍
API
API
=
nicknameField.rx.text.orEmpty
nicknameField.rx.text.orEmpty
.map { nickname -> Bool in
// return true of false
}
🤔 ?
nicknameField.rx.text.orEmpty
.map { nickname -> Bool in
// return true of false
}
nicknameField.rx.text.orEmpty
. map { nickname -> Bool in
}
nicknameField.rx.text.orEmpty
.flatMap { nickname -> Observable<Bool> in
}
nicknameField.rx.text.orEmpty
.flatMap { nickname -> Observable<Bool> in
return API.checkNickname(nickname)
}
nicknameField.rx.text.orEmpty
.flatMap { nickname -> Observable<Bool> in
return API.checkNickname(nickname)
}
.map { isAva...
nicknameField.rx.text.orEmpty
.flatMap { nickname -> Observable<Bool> in
return API.checkNickname(nickname)
}
.map { isAva...
map() vs flatMap()
20 40 60 80
map(x => x * 2)
10 20 30 40
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
map() vs flatMap()
flatMap( => )
Nickname
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNic...
nicknameField.rx.text.orEmpty
.flatMap { nickname -> Observable<Bool> in
return API.checkNickname(nickname)
}
.map { isAva...
nicknameField.rx.text.orEmpty
.debounce(0.3, scheduler: MainScheduler.instance)
.flatMap { nickname -> Observable<Bool> in...
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNic...
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNic...
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNickname(" ")
checkNic...
1 4
debounce
1 2 3 4
, Observable
Timer
00:17
Timer
00:17
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(tick)
})
Timer
00:17
Start
17
18
19
20
21
...
Start
Start
Observable
Timer
00:17
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(tick)
})
Timer
00:17
var disposeBag = DisposeBag()
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(...
Timer
00:17
var disposeBag = DisposeBag()
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(...
var disposeBag = DisposeBag()
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(tick)
})
.di...
var disposeBag = DisposeBag()
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(tick)
})
.di...
var disposeBag = DisposeBag()
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(tick)
})
.di...
var disposeBag = DisposeBag()
Observable<Int>
.interval(1, scheduler: ...)
.subscribe(onNext: { tick in
print(tick)
})
.di...
•
•
•
RxSwift
http://reactivex.io
http://rxswift.org
http://community.rxswift.org
https://rxswift-slack.herokuapp.com
.
(github.com/devxoul)
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
RxSwift 시작하기
Upcoming SlideShare
Loading in …5
×

RxSwift 시작하기

1,931 views

Published on

2017 소프트웨어 마에스트로 100+ 컨퍼런스 기술 세미나에서 발표한 자료입니다.

Published in: Software
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

RxSwift 시작하기

  1. 1. RxSwift (github.com/devxoul)
  2. 2. • StyleShare Inc. • SW Maestro 2 • RxSwift
  3. 3. RxSwift?
  4. 4. RxSwift = ReactiveX + Swift
  5. 5. RxSwift = ReactiveX + Swift
  6. 6. RxSwift = ReactiveX + Swift ?
  7. 7. RxSwift = ReactiveX + Swift Re + ActiveX
  8. 8. RxSwift = ReactiveX + Swift Reactive + Extension
  9. 9. RxSwift = ReactiveX + Swift
  10. 10. RxSwift = ReactiveX + Swift ?
  11. 11. a = 10 b = a * 2
  12. 12. a = 10 b = a * 2 print(b)
  13. 13. a = 10 b = a * 2 print(b) // 20
  14. 14. a = 10 b = a * 2 print(b) // 20 a = 30
  15. 15. a = 10 b = a * 2 print(b) // 20 a = 30 print(b)
  16. 16. a = 10 b = a * 2 print(b) // 20 a = 30 print(b) // 20
  17. 17. a = 10 b = a * 2 print(b) // 20 a = 30 print(b) // 20 60
  18. 18. ReactiveX Observer Pattern Iterator Pattern Functional Programming
  19. 19. ReactiveX Observer Pattern Iterator Pattern Functional Programming
  20. 20. Observable Observer
  21. 21. Observable Observer observe
  22. 22. Observable Observer observe notify
  23. 23. Observable ObserverObserver Observer
  24. 24. ReactiveX Observer Pattern Iterator Pattern Functional Programming
  25. 25. Iterator next() hasNext()
  26. 26. Iterator next() hasNext() 10 20 30 40
  27. 27. Iterator next() hasNext() 10 20 30 40
  28. 28. Iterator next() hasNext() 10 20 30 40 iterator.next()
  29. 29. Iterator next() hasNext() 10 20 30 40 iterator.next() // 10
  30. 30. Iterator next() hasNext() 10 20 30 40
  31. 31. Iterator next() hasNext() 10 20 30 40 iterator.next()
  32. 32. Iterator next() hasNext() 10 20 30 40 iterator.next() // 20
  33. 33. Iterator next() hasNext() 10 20 30 40
  34. 34. Iterator next() hasNext() 10 20 30 40 iterator.next()
  35. 35. Iterator next() hasNext() 10 20 30 40 iterator.next() // 30
  36. 36. Iterator next() hasNext() 10 20 30 40
  37. 37. Iterator next() hasNext() 10 20 30 40 iterator.next()
  38. 38. Iterator next() hasNext() 10 20 30 40 iterator.next() // 40
  39. 39. Iterator next() hasNext() 10 20 30 40
  40. 40. Iterator next() hasNext() 10 20 30 40 iterator.hasNext() // false
  41. 41. ReactiveX Observer Pattern Iterator Pattern Functional Programming
  42. 42. • • ,
  43. 43. • • • ... higher-order fuction pure fuction
  44. 44. • • • ... higher-order fuction pure fuction
  45. 45. 1. 2.
  46. 46. var array = [2, 6, 3, 1, 7] array.sort(by: { a, b in return a < b })
  47. 47. var array = [2, 6, 3, 1, 7] array.sort(by: { a, b in return a < b })
  48. 48. var array = [2, 6, 3, 1, 7] array.sort(by: { a, b in return a < b })
  49. 49. • • • ... higher-order fuction pure fuction
  50. 50. • •
  51. 51. • • ( , , I/O )
  52. 52. • •
  53. 53. var rate = 1130 func krw(usd: Int) -> Int { return usd * rate }
  54. 54. var rate = 1130 func krw(usd: Int) -> Int { return usd * rate } krw(usd: 2) // 2260 krw(usd: 3) // 3390
  55. 55. var rate = 1130 func krw(usd: Int) -> Int { return usd * rate } rate = 1140 krw(usd: 2) // 2260 krw(usd: 3) // 3390
  56. 56. var rate = 1130 func krw(usd: Int) -> Int { return usd * rate } rate = 1140 krw(usd: 2) // 2260 2280 krw(usd: 3) // 3390 3420
  57. 57. var rate = 1130 func krw(usd: Int) -> Int { return usd * rate } rate = 1140 krw(usd: 2) // 2260 2280 krw(usd: 3) // 3390 3420
  58. 58. var rate = 1130 func krw(usd: Int) -> Int { return usd * rate } rate = 1140 krw(usd: 2) // 2260 2280 krw(usd: 3) // 3390 3420
  59. 59. func krw(usd: Int) -> Int { return usd * rate }
  60. 60. func krw(usd: Int ) -> Int { return usd * rate }
  61. 61. func krw(usd: Int, rate: Int) -> Int { return usd * rate }
  62. 62. func krw(usd: Int, rate: Int) -> Int { return usd * rate }
  63. 63. ReactiveX Observable Pattern Iterator Pattern Functional Programming
  64. 64. a 10 b a * 2
  65. 65. a 10 b 20
  66. 66. a b
  67. 67. 10 20 30 40a 20 40 60 80b
  68. 68. 10 20 30 40a 20 40 60 80b
  69. 69. 10 20 30 40a 20 40 60 80b map(x => x * 2)
  70. 70. 10 20 30 40a 20 40 60 80b map(x => x * 2) Marble Diagrams
  71. 71. 20 40 60 80b map(x => x * 2) Observable.from([10, 20, 30, 40])
  72. 72. Observable.from([10, 20, 30, 40]) .map { $0 * 2 }
  73. 73. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  74. 74. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  75. 75. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  76. 76. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) // 20 })
  77. 77. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  78. 78. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  79. 79. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) // 40 })
  80. 80. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  81. 81. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  82. 82. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) // 60 })
  83. 83. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  84. 84. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) })
  85. 85. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) // 80 })
  86. 86. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) // 80 }) Observable
  87. 87. Observable.from([10, 20, 30, 40]) .map { $0 * 2 } .subscribe(onNext: { value in print(value) // 80 }) Observer
  88. 88. Password (4 )
  89. 89. 1 (4 ) . ❌
  90. 90. 12 (4 ) . ❌
  91. 91. 123 (4 ) . ❌
  92. 92. 1234 (4 ) . 👍
  93. 93. "1"
  94. 94. "1" map(str => str.length >= 4)
  95. 95. "1" map(str => str.length >= 4) false
  96. 96. "1" false map(str => str.length >= 4) map(valid => getMessage(valid))
  97. 97. "1" false map(str => str.length >= 4) "❌ " map(valid => getMessage(valid))
  98. 98. "1" "12" false map(str => str.length >= 4) "❌ " map(valid => getMessage(valid))
  99. 99. "1" "12" false false map(str => str.length >= 4) "❌ " map(valid => getMessage(valid))
  100. 100. "1" "12" false false map(str => str.length >= 4) "❌ " "❌ " map(valid => getMessage(valid))
  101. 101. "1" "12" "123" false false map(str => str.length >= 4) "❌ " "❌ " map(valid => getMessage(valid))
  102. 102. "1" "12" "123" false false false map(str => str.length >= 4) "❌ " "❌ " map(valid => getMessage(valid))
  103. 103. "1" "12" "123" false false false map(str => str.length >= 4) "❌ " "❌ " "❌ " map(valid => getMessage(valid))
  104. 104. "1" "12" "123" "1234" false false false map(str => str.length >= 4) "❌ " "❌ " "❌ " map(valid => getMessage(valid))
  105. 105. "1" "12" "123" "1234" false false false true map(str => str.length >= 4) "❌ " "❌ " "❌ " map(valid => getMessage(valid))
  106. 106. false false false true map(str => str.length >= 4) map(valid => getMessage(valid)) "1" "12" "123" "1234" "❌ " "❌ " "❌ " "👍"
  107. 107. passwordField.rx.text.orEmpty
  108. 108. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 }
  109. 109. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in }
  110. 110. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } }
  111. 111. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  112. 112. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) "1"
  113. 113. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) false
  114. 114. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  115. 115. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  116. 116. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) "12"
  117. 117. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) false
  118. 118. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  119. 119. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  120. 120. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) "123"
  121. 121. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) false
  122. 122. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  123. 123. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  124. 124. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) "1234"
  125. 125. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message }) true
  126. 126. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  127. 127. passwordField.rx.text.orEmpty .map { $0.characters.count >= 4 } .map { isValid in if isValid { return " . 👍" } else { return " . ❌" } } .subscribe(onNext: { [weak self] message in self?.messageLabel.rx.text = message })
  128. 128. : Observable<String> : Observable<Int> : Observable<Void> : Observable<CGPoint> ...
  129. 129. Observable
  130. 130. "1" "12" "123" "1234"
  131. 131. "1"
  132. 132. "1"
  133. 133. "1" "12"
  134. 134. "1" "12"
  135. 135. "1" "12" "123"
  136. 136. "1" "12" "123"
  137. 137. "1" "12" "123" "1234"
  138. 138. Nickname
  139. 139. . ❌
  140. 140. . ❌
  141. 141. . 👍
  142. 142. API
  143. 143. API =
  144. 144. nicknameField.rx.text.orEmpty
  145. 145. nicknameField.rx.text.orEmpty .map { nickname -> Bool in // return true of false }
  146. 146. 🤔 ? nicknameField.rx.text.orEmpty .map { nickname -> Bool in // return true of false }
  147. 147. nicknameField.rx.text.orEmpty . map { nickname -> Bool in }
  148. 148. nicknameField.rx.text.orEmpty .flatMap { nickname -> Observable<Bool> in }
  149. 149. nicknameField.rx.text.orEmpty .flatMap { nickname -> Observable<Bool> in return API.checkNickname(nickname) }
  150. 150. nicknameField.rx.text.orEmpty .flatMap { nickname -> Observable<Bool> in return API.checkNickname(nickname) } .map { isAvailable in return getMessage(isAvailable) }
  151. 151. nicknameField.rx.text.orEmpty .flatMap { nickname -> Observable<Bool> in return API.checkNickname(nickname) } .map { isAvailable in return getMessage(isAvailable) } .subscribe(onNext: { [weak self] message in self?.messageLabel.text = message })
  152. 152. map() vs flatMap() 20 40 60 80 map(x => x * 2) 10 20 30 40
  153. 153. map() vs flatMap() flatMap( => )
  154. 154. map() vs flatMap() flatMap( => )
  155. 155. map() vs flatMap() flatMap( => )
  156. 156. map() vs flatMap() flatMap( => )
  157. 157. map() vs flatMap() flatMap( => )
  158. 158. map() vs flatMap() flatMap( => )
  159. 159. map() vs flatMap() flatMap( => )
  160. 160. map() vs flatMap() flatMap( => )
  161. 161. map() vs flatMap() flatMap( => )
  162. 162. map() vs flatMap() flatMap( => )
  163. 163. map() vs flatMap() flatMap( => )
  164. 164. Nickname
  165. 165. checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ")
  166. 166. nicknameField.rx.text.orEmpty .flatMap { nickname -> Observable<Bool> in return API.checkNickname(nickname) } .map { isAvailable in return getMessage(isAvailable) } .subscribe(onNext: { [weak self] message in self?.messageLabel.text = message })
  167. 167. nicknameField.rx.text.orEmpty .debounce(0.3, scheduler: MainScheduler.instance) .flatMap { nickname -> Observable<Bool> in return API.checkNickname(nickname) } .map { isAvailable in return getMessage(isAvailable) } .subscribe(onNext: { [weak self] message in self?.messageLabel.text = message })
  168. 168. checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ")
  169. 169. checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") 0.3s 0.3s 0.3s
  170. 170. checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") checkNickname(" ") 0.3s 0.3s 0.3s
  171. 171. 1 4 debounce 1 2 3 4
  172. 172. , Observable
  173. 173. Timer 00:17
  174. 174. Timer 00:17 Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) })
  175. 175. Timer 00:17
  176. 176. Start
  177. 177. 17 18 19 20 21 ... Start
  178. 178. Start Observable
  179. 179. Timer 00:17 Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) })
  180. 180. Timer 00:17 var disposeBag = DisposeBag() Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) }) .disposed(by: disposeBag)
  181. 181. Timer 00:17 var disposeBag = DisposeBag() Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) }) .disposed(by: disposeBag)
  182. 182. var disposeBag = DisposeBag() Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) }) .disposed(by: disposeBag) Start
  183. 183. var disposeBag = DisposeBag() Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) }) .disposed(by: disposeBag) Start
  184. 184. var disposeBag = DisposeBag() Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) }) .disposed(by: disposeBag) Start
  185. 185. var disposeBag = DisposeBag() Observable<Int> .interval(1, scheduler: ...) .subscribe(onNext: { tick in print(tick) }) .disposed(by: disposeBag) Start Dispose
  186. 186. • • • RxSwift
  187. 187. http://reactivex.io http://rxswift.org http://community.rxswift.org https://rxswift-slack.herokuapp.com
  188. 188. . (github.com/devxoul)

×