SlideShare a Scribd company logo
1 of 31
Download to read offline
RxSwift 예제로 감잡기
RxSwift 시작을 위한 간단한 예제들
유용하
@inkyfox
github.com/inkyfox
ReactiveX
• 왜 쓰는가?
• 장점?
• 설치는?
• 비동기.. 함수형.. LINQ.. MVVM..?
• Observable? Observer?
ReactiveX
• 왜 쓰는가?
• 장점?
• 설치는?
• 비동기.. 함수형.. LINQ.. MVVM..?
• Observable? Observer?
일단 생략
ReactiveX
먼저 코드 예제를 보며 감을 잡아 보는 걸로
UI Event
func reload() { }
func setup() {
reloadButton.rx.tap // Observable<Void>
.subscribe(onNext: { [weak self] in self?.reload() })
.addDisposableTo(disposeBag)
}
UI Event
func reload() { }
func setup() {
reloadButton.rx.tap // Observable<Void>
.subscribe(onNext: { [weak self] in self?.reload() })
.addDisposableTo(disposeBag)
}
UI Event
func reload() { }
func setup() {
reloadButton.rx.tap // Observable<Void>
.bindNext(reload)
.addDisposableTo(disposeBag)
}
UI Event
func reload() { }
func setup() {
reloadButton.rx.tap // Observable<Void>
.do(onNext: {
print(“Reload Button Clicked.”)
Analytics.buttonReload.send()
})
.bindNext(reload)
.addDisposableTo(disposeBag)
}
UI Event
func reload() { }
func setup() {
reloadButton.rx.tap // Observable<Void>
.debounce(0.3, scheduler: MainScheduler.instance)
.do(onNext: {
print(“Reload Button Clicked.”)
Analytics.buttonReload.send()
})
.bindNext(reload)
.addDisposableTo(disposeBag)
}
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.map { json in Page(json: json) } // Observable<Page>
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] page in
self?.display(page: page)
})
.addDisposableTo(reloadDisposeBag)
}
func display(page: Page) { }
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.map { json in Page(json: json) } // Observable<Page>
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] page in
self?.display(page: page)
})
.addDisposableTo(reloadDisposeBag)
}
func display(page: Page) { }
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.map { json in Page(json: json) } // Observable<Page>
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] page in
self?.display(page: page)
})
.addDisposableTo(reloadDisposeBag)
}
func display(page: Page) { }
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.map { json in Page(json: json) } // Observable<Page>
.observeOn(MainScheduler.instance)
.bindNext(display)
.addDisposableTo(reloadDisposeBag)
}
func display(page: Page) { }
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.map { Page(json: $0) } // Observable<Page>
.observeOn(MainScheduler.instance)
.bindNext(display)
.addDisposableTo(reloadDisposeBag)
}
func display(page: Page) { }
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.retry(2)
.map { Page(json: $0) } // Observable<Page>
.observeOn(MainScheduler.instance)
.bindNext(display)
.addDisposableTo(reloadDisposeBag)
}
func display(page: Page) { }
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.subscribeOn(SerialDispatchQueueScheduler(qos: .background))
.retry(2)
.observeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.map(Page.init) // Observable<Page>
.observeOn(MainScheduler.instance)
.bindNext(display)
.addDisposableTo(reloadDisposeBag)
}
func display(page: Page) { }
REST API
func reload() {
API.default.request(.getPage) // Observable<JSON>
.subscribeOn(SerialDispatchQueueScheduler(qos: .background))
.retry(2)
.observeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.map(Page.init) // Observable<Page>
.observeOn(MainScheduler.instance)
.do(
onNext: { print("Reload success: ($0)") },
onError: { error in print("Reload failed! (error)") },
onCompleted: { print("Reload completed") }
)
.bindNext(display)
.addDisposableTo(reloadDisposeBag)
}
Property Binding
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] reloading in
self?.reloadButton.isEnabled = !reloading
})
.addDisposableTo(disposeBag)
}
Property Binding
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] reloading in
self?.reloadButton.isEnabled = !reloading
})
.addDisposableTo(disposeBag)
}
Property Binding
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.map { !$0 }
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] enabled in
self?.reloadButton.isEnabled = enabled
})
.addDisposableTo(disposeBag)
}
Property Binding
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.map { !$0 }
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] enabled in
self?.reloadButton.isEnabled = enabled
})
.addDisposableTo(disposeBag)
}
Property Binding
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.map { !$0 }
.observeOn(MainScheduler.instance)
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
}
Merge Operator
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.map { !$0 }
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
reloadButton.rx.tap // Observable<Void>
.map { false } // Observable<Bool>
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
}
Merge Operator
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.map { !$0 }
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
reloadButton.rx.tap // Observable<Void>
.map { false } // Observable<Bool>
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
}
Merge Operator
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // Observable<Bool>
.map { !$0 }
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
reloadButton.rx.tap // Observable<Void>
.map { false } // Observable<Bool>
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
}
Merge Operator
let isReloading: Variable<Bool> = Variable(false)
func setup() {
Observable.from(
[isReloading.asObservable().map { !$0 },
reloadButton.rx.tap.map { false } ]
).merge() // Observable<Bool>
.bindTo(reloadButton.rx.isEnabled)
.addDisposableTo(disposeBag)
}
Operators
let isReloading: Variable<Bool> = Variable(false)
func setup() {
isReloading.asObservable() // |-F-T-F-T-F-
.filter { $0 == false } // |-F---F---F-
.skip(1) // |-----F---F-
.take(1) // |-----F|
.observeOn(MainScheduler.instance)
.bindTo(messageView.rx.isHidden)
.addDisposableTo(disposeBag)
}
그 밖에
• NotificationCenter
• Animation
• 등의 모든 이벤트
• 예제: https://github.com/inkyfox/RxCurrency_iOS
ReactiveX
• Pulling이 아닌 Pushing Data (수동적)
• LINQ style 연산자 & 함수형 프로그래밍
• 비동기 (Async) 프로그래밍
ReactiveX
앞의 예제들을
Callback (Delegate pattern)으로 했으면
어땠을까 상상해봅시다
공부
• http://www.introtorx.com
• http://reactivex.io/intro.html
• http://rxmarbles.com
• https://github.com/ReactiveX/RxSwift/tree/master/
Documentation

More Related Content

What's hot

Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Wilson Su
 
Pimp your site with jQuery!
Pimp your site with jQuery!Pimp your site with jQuery!
Pimp your site with jQuery!Elliott Kember
 
Java осень 2012 лекция 6
Java осень 2012 лекция 6Java осень 2012 лекция 6
Java осень 2012 лекция 6Technopark
 
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Loïc Knuchel
 
Javascript and jQuery for Mobile
Javascript and jQuery for MobileJavascript and jQuery for Mobile
Javascript and jQuery for MobileIvano Malavolta
 
Semana 12 interfaces gráficas de usuario
Semana 12   interfaces gráficas de usuarioSemana 12   interfaces gráficas de usuario
Semana 12 interfaces gráficas de usuarioTerryJoss
 
UISearchController par Stéphane sudre
UISearchController par Stéphane sudreUISearchController par Stéphane sudre
UISearchController par Stéphane sudreCocoaHeads France
 
Jak zabít několik much jednou ranou přechodem na fragmenty
Jak zabít několik much jednou ranou přechodem na fragmentyJak zabít několik much jednou ranou přechodem na fragmenty
Jak zabít několik much jednou ranou přechodem na fragmentyDavid Vávra
 
aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.bhavesh lande
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasJavier Eguiluz
 
Collection pipeline par Mathieu Godart
Collection pipeline par  Mathieu GodartCollection pipeline par  Mathieu Godart
Collection pipeline par Mathieu GodartCocoaHeads France
 

What's hot (20)

Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8
 
Pimp your site with jQuery!
Pimp your site with jQuery!Pimp your site with jQuery!
Pimp your site with jQuery!
 
Jquery ui, ajax
Jquery ui, ajaxJquery ui, ajax
Jquery ui, ajax
 
Underscore.js
Underscore.jsUnderscore.js
Underscore.js
 
Java осень 2012 лекция 6
Java осень 2012 лекция 6Java осень 2012 лекция 6
Java осень 2012 лекция 6
 
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
 
Javascript and jQuery for Mobile
Javascript and jQuery for MobileJavascript and jQuery for Mobile
Javascript and jQuery for Mobile
 
Semana 12 interfaces gráficas de usuario
Semana 12   interfaces gráficas de usuarioSemana 12   interfaces gráficas de usuario
Semana 12 interfaces gráficas de usuario
 
UISearchController par Stéphane sudre
UISearchController par Stéphane sudreUISearchController par Stéphane sudre
UISearchController par Stéphane sudre
 
Silex al límite
Silex al límiteSilex al límite
Silex al límite
 
JQuery
JQueryJQuery
JQuery
 
jQuery PLUGIN
jQuery PLUGINjQuery PLUGIN
jQuery PLUGIN
 
Jak zabít několik much jednou ranou přechodem na fragmenty
Jak zabít několik much jednou ranou přechodem na fragmentyJak zabít několik much jednou ranou přechodem na fragmenty
Jak zabít několik much jednou ranou přechodem na fragmenty
 
Jquery p1
Jquery p1Jquery p1
Jquery p1
 
aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.
 
Sis quiz
Sis quizSis quiz
Sis quiz
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
 
Collection pipeline par Mathieu Godart
Collection pipeline par  Mathieu GodartCollection pipeline par  Mathieu Godart
Collection pipeline par Mathieu Godart
 
Dwr实战
Dwr实战Dwr实战
Dwr实战
 
Devsumi Openjam
Devsumi OpenjamDevsumi Openjam
Devsumi Openjam
 

RxSwift 예제로 감잡기

  • 1. RxSwift 예제로 감잡기 RxSwift 시작을 위한 간단한 예제들 유용하 @inkyfox github.com/inkyfox
  • 2. ReactiveX • 왜 쓰는가? • 장점? • 설치는? • 비동기.. 함수형.. LINQ.. MVVM..? • Observable? Observer?
  • 3. ReactiveX • 왜 쓰는가? • 장점? • 설치는? • 비동기.. 함수형.. LINQ.. MVVM..? • Observable? Observer? 일단 생략
  • 4. ReactiveX 먼저 코드 예제를 보며 감을 잡아 보는 걸로
  • 5. UI Event func reload() { } func setup() { reloadButton.rx.tap // Observable<Void> .subscribe(onNext: { [weak self] in self?.reload() }) .addDisposableTo(disposeBag) }
  • 6. UI Event func reload() { } func setup() { reloadButton.rx.tap // Observable<Void> .subscribe(onNext: { [weak self] in self?.reload() }) .addDisposableTo(disposeBag) }
  • 7. UI Event func reload() { } func setup() { reloadButton.rx.tap // Observable<Void> .bindNext(reload) .addDisposableTo(disposeBag) }
  • 8. UI Event func reload() { } func setup() { reloadButton.rx.tap // Observable<Void> .do(onNext: { print(“Reload Button Clicked.”) Analytics.buttonReload.send() }) .bindNext(reload) .addDisposableTo(disposeBag) }
  • 9. UI Event func reload() { } func setup() { reloadButton.rx.tap // Observable<Void> .debounce(0.3, scheduler: MainScheduler.instance) .do(onNext: { print(“Reload Button Clicked.”) Analytics.buttonReload.send() }) .bindNext(reload) .addDisposableTo(disposeBag) }
  • 10. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .map { json in Page(json: json) } // Observable<Page> .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] page in self?.display(page: page) }) .addDisposableTo(reloadDisposeBag) } func display(page: Page) { }
  • 11. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .map { json in Page(json: json) } // Observable<Page> .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] page in self?.display(page: page) }) .addDisposableTo(reloadDisposeBag) } func display(page: Page) { }
  • 12. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .map { json in Page(json: json) } // Observable<Page> .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] page in self?.display(page: page) }) .addDisposableTo(reloadDisposeBag) } func display(page: Page) { }
  • 13. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .map { json in Page(json: json) } // Observable<Page> .observeOn(MainScheduler.instance) .bindNext(display) .addDisposableTo(reloadDisposeBag) } func display(page: Page) { }
  • 14. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .map { Page(json: $0) } // Observable<Page> .observeOn(MainScheduler.instance) .bindNext(display) .addDisposableTo(reloadDisposeBag) } func display(page: Page) { }
  • 15. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .retry(2) .map { Page(json: $0) } // Observable<Page> .observeOn(MainScheduler.instance) .bindNext(display) .addDisposableTo(reloadDisposeBag) } func display(page: Page) { }
  • 16. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .subscribeOn(SerialDispatchQueueScheduler(qos: .background)) .retry(2) .observeOn(ConcurrentDispatchQueueScheduler(qos: .background)) .map(Page.init) // Observable<Page> .observeOn(MainScheduler.instance) .bindNext(display) .addDisposableTo(reloadDisposeBag) } func display(page: Page) { }
  • 17. REST API func reload() { API.default.request(.getPage) // Observable<JSON> .subscribeOn(SerialDispatchQueueScheduler(qos: .background)) .retry(2) .observeOn(ConcurrentDispatchQueueScheduler(qos: .background)) .map(Page.init) // Observable<Page> .observeOn(MainScheduler.instance) .do( onNext: { print("Reload success: ($0)") }, onError: { error in print("Reload failed! (error)") }, onCompleted: { print("Reload completed") } ) .bindNext(display) .addDisposableTo(reloadDisposeBag) }
  • 18. Property Binding let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] reloading in self?.reloadButton.isEnabled = !reloading }) .addDisposableTo(disposeBag) }
  • 19. Property Binding let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] reloading in self?.reloadButton.isEnabled = !reloading }) .addDisposableTo(disposeBag) }
  • 20. Property Binding let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .map { !$0 } .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] enabled in self?.reloadButton.isEnabled = enabled }) .addDisposableTo(disposeBag) }
  • 21. Property Binding let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .map { !$0 } .observeOn(MainScheduler.instance) .subscribe(onNext: { [weak self] enabled in self?.reloadButton.isEnabled = enabled }) .addDisposableTo(disposeBag) }
  • 22. Property Binding let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .map { !$0 } .observeOn(MainScheduler.instance) .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) }
  • 23. Merge Operator let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .map { !$0 } .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) reloadButton.rx.tap // Observable<Void> .map { false } // Observable<Bool> .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) }
  • 24. Merge Operator let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .map { !$0 } .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) reloadButton.rx.tap // Observable<Void> .map { false } // Observable<Bool> .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) }
  • 25. Merge Operator let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // Observable<Bool> .map { !$0 } .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) reloadButton.rx.tap // Observable<Void> .map { false } // Observable<Bool> .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) }
  • 26. Merge Operator let isReloading: Variable<Bool> = Variable(false) func setup() { Observable.from( [isReloading.asObservable().map { !$0 }, reloadButton.rx.tap.map { false } ] ).merge() // Observable<Bool> .bindTo(reloadButton.rx.isEnabled) .addDisposableTo(disposeBag) }
  • 27. Operators let isReloading: Variable<Bool> = Variable(false) func setup() { isReloading.asObservable() // |-F-T-F-T-F- .filter { $0 == false } // |-F---F---F- .skip(1) // |-----F---F- .take(1) // |-----F| .observeOn(MainScheduler.instance) .bindTo(messageView.rx.isHidden) .addDisposableTo(disposeBag) }
  • 28. 그 밖에 • NotificationCenter • Animation • 등의 모든 이벤트 • 예제: https://github.com/inkyfox/RxCurrency_iOS
  • 29. ReactiveX • Pulling이 아닌 Pushing Data (수동적) • LINQ style 연산자 & 함수형 프로그래밍 • 비동기 (Async) 프로그래밍
  • 30. ReactiveX 앞의 예제들을 Callback (Delegate pattern)으로 했으면 어땠을까 상상해봅시다
  • 31. 공부 • http://www.introtorx.com • http://reactivex.io/intro.html • http://rxmarbles.com • https://github.com/ReactiveX/RxSwift/tree/master/ Documentation