SECON'2016. Мухаметов Андрей, RxSwift && Apple TV - так ли хорошо всё новое?
Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift
-
Upload
aaron-douglas -
Category
Technology
-
view
271 -
download
1
Transcript of Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift
SWIFT & REACTIVEXAsynchronous Event-Based Funsies with RxSwift
WHO I AM➤ Aaron Douglas
➤ Milwaukee, WI USA
➤ Mobile Maker for Automattic (WordPress.com)
➤ Remote full time 3+ years
➤ @astralbodies
REACTIVE?FUNCTIONAL?
MEH?
FUNCTIONAL & REACTIVE PROGRAMMING
➤ Reactive Programming
➤ Asynchronous Data Flow
➤ Functional Programming
➤ Map, Reduce, Filter
➤ Avoiding State
➤ Immutable Data
➤ Declarative Paradigm - logic of computation rather than describing flow
➤ Implementations - ReactiveCocoa/RAC, RxSwift
WHAT IS RXSWIFT?
WHAT IS RXSWIFT?
➤ Based on ReactiveX
➤ Many different ports: Java, JavaScript, .NET, Scala, Clojure, Swift, Kotlin, PHP, …
➤ Extends the Observer Pattern
➤ Related to Iterable Pattern
➤ Swift itself provides some protocols with equivalence
➤ SequenceType
➤ GeneratorType
OBSERVER PATTERN
NSNOTIFICATIONCENTER
NSNotificationCenter .defaultCenter() .addObserver(self, selector:"downloadImage:", name: "BLDownloadImageNotification", object: nil)
NSNotificationCenter .defaultCenter() .postNotificationName("BLDownloadImageNotification", object: self, userInfo: ["imageView": coverImage, "coverUrl": albumCover])
OBSERVER PATTERN
9
ITERATOR PATTERN
ITERATOR PATTERN
GENERATORS, SEQUENCES, OH MY!
GENERATORS
public protocol GeneratorType { associatedtype Element public mutating func next() -> Self.Element? }
GENERATORSclass CountdownGenerator: GeneratorType { typealias Element = Int var element: Element init<T>(array: [T]) { self.element = array.count } func next() -> Element? { guard element > 0 else { return nil } element -= 1 return element } }
let xs = ["A", "B", "C"] let generator = CountdownGenerator(array: xs) while let i = generator.next() { print("Element \(i) of the array is \(xs[i])") }
Element 2 of the array is C Element 1 of the array is B Element 0 of the array is A
SEQUENCES
public protocol SequenceType { associatedtype Generator : GeneratorType public func generate() -> Self.Generator }
SEQUENCESclass ReverseSequence<T>: SequenceType { var array: [T] init(array: [T]) { self.array = array } func generate() -> CountdownGenerator { return CountdownGenerator(array: array) } }
let reverseSequence = ReverseSequence(array: xs) let reverseGenerator = reverseSequence.generate()
while let i = reverseGenerator.next() { print("Index \(i) is \(xs[i])") }
for i in ReverseSequence(array: xs) { print("Index \(i) is \(xs[i])") }
Index 2 is C Index 1 is B Index 0 is A
Index 2 is C Index 1 is B Index 0 is A
OBSERVABLES
OBSERVERTYPE
public protocol ObserverType { associatedtype E
func on(event: Event<E>) }
public enum Event<Element> { case Next(Element) case Error(ErrorType) case Completed }
OBSERVABLETYPE
public protocol ObservableType : ObservableConvertibleType { associatedtype E func subscribe<O: ObserverType where O.E == E>(observer: O) -> Disposable }
public protocol ObservableConvertibleType { associatedtype E
func asObservable() -> Observable<E> }
VISUALIZATIONS OF SEQUENCES
--1--2--3--4--5--6--| // terminates normally
--a--b--a--a--a---d---X // terminates with error
---tap-tap-------tap---> // infinite; never ends
MAKING AN OBSERVABLE
let disposeBag = DisposeBag() Observable.just("X") .subscribe { event in print(event) } .addDisposableTo(disposeBag)
MAKING AN OBSERVABLE
let disposeBag = DisposeBag() Observable.of("W", "X", "Y", "X") .subscribeNext { element in print(element) } .addDisposableTo(disposeBag)
MAKING AN OBSERVABLE
let disposeBag = DisposeBag() ["W", "X", "Y", "Z"].toObservable() .subscribeNext { print($0) } .addDisposableTo(disposeBag)
SUBSCRIBING
someObservable.subscribe( onNext: { print("Element: ", $0) }, onError: { print("Error: ", $0) }, onCompleted: { print("Completed") }, onDisposed: { print("Disposed") } )
someObservable .subscribeNext { print("Element: ", $0) }
OPERATORS
MAP
MAP
let disposeBag = DisposeBag() Observable.of(1, 2, 3) .map { $0 * 10 } .subscribeNext { print($0) } .addDisposableTo(disposeBag)
---
10 20 30
FILTER
FILTER
let disposeBag = DisposeBag()
Observable.of(2, 30, 22, 5, 60, 1) .filter { $0 > 10 } .subscribeNext { print($0) } .addDisposableTo(disposeBag)
---
30 22 60
SCAN
SCANlet disposeBag = DisposeBag() Observable.of(1, 2, 3, 4, 5) .scan(0) { aggregateValue, newValue in aggregateValue + newValue } .subscribeNext { print($0) } .addDisposableTo(disposeBag)
---
1 3 6 10 15
MERGE
MERGElet disposeBag = DisposeBag() let subject1 = PublishSubject<String>() let subject2 = PublishSubject<String>() Observable.of(subject1, subject2) .merge() .subscribeNext { print($0) } .addDisposableTo(disposeBag) subject1.onNext("20") subject1.onNext("40") subject1.onNext("60")
subject2.onNext("1") subject1.onNext("80") subject1.onNext("100")
subject2.onNext("1")
20 40 60 1 80 100 1
RXMARBLES.COM
DISPOSING
.dispose()
.addDisposableTo(disposeBag)
COCOA + RXSWIFT
BINDINGS
totCountStepper .rx_value .subscribeNext { value in self.totalNumberOfTots.value = Int(value) } .addDisposableTo(disposeBag)
BINDINGS➤ NSTextStorage
➤ UIActivityIndicatorView
➤ UIAlertAction
➤ UIApplication
➤ UIBarButtonItem
➤ UIButton
➤ UICollectionView
➤ UIControl
➤ UIDatePicker
➤ UIGestureRecognizer
➤ UIImagePickerController
➤ UIImageView
➤ UILabel
➤ UINavigationItem
➤ UIPageControl
➤ UIPickerView
➤ UIProgressView
➤ UIRefreshControl
➤ UIScrollView
➤ UISearchBar
➤ UISearchController
➤ UISegmentedControl
➤ UISlider
➤ UIStepper
➤ UISwitch
➤ UITabBar
➤ UITabBarItem
➤ UITableView
➤ UITextField
➤ UITextView
➤ UIView
➤ UIViewController
AN EXAMPLE
TATER TOT TIMER
RXSWIFT IN THE WILD
WHERE TO LEARN MORE
WHERE TO LEARN MORE
➤ ReactiveX RxSwift main repo
➤ https://github.com/ReactiveX/RxSwift/
➤ FRP iOS Learning Resources
➤ https://gist.github.com/JaviLorbada/4a7bd6129275ebefd5a6
➤ Functional Reactive Programming with RxSwift
➤ https://realm.io/news/slug-max-alexander-functional-reactive-rxswift/
➤ RxSwift Slack
➤ http://rxswift-slack.herokuapp.com/
AARON DOUGLAS@astralbodies
http://astralbodi.es