shtnkgm
October 02, 2018
130

# SwiftとFunctional Reactive Programming

- Swift
- Functional Reactive Programming
- RxSwift

October 02, 2018

## Transcript

3. ### ؔ਺ܕϦΞΫςΟϒϓϩάϥϛϯά • Functional Reactive ProgrammingʢFRPʣ • FRP͸ϓϩάϥϛϯάύϥμΠϜͷҰͭ • ؔ਺ܕϓϩάϥϛϯά +

ϦΞΫςΟϒϓϩάϥϛϯά

8. ### ղ౴ྫ1 1͔Β10·Ͱͷ੔਺Λ3ഒͯ͠ɺ6ͷഒ਺ͷΈ഑ྻΛੜ੒ var result = [Int]() for number in 1...10

{ let tripleNumber = number * 3 if tripleNumber % 6 == 0 { result += [tripleNumber] } }
9. ### ղ౴ྫ2 1͔Β10·Ͱͷ੔਺Λ3ഒͯ͠ɺ6ͷഒ਺ͷΈ഑ྻΛੜ੒ let result = (1...10).map { \$0 * 3

}.filter { \$0 % 6 == 0 }

11. ### ղ౴ྫ1ʣ໋ྩܕϓϩάϥϛϯά var result = [Int]() for number in 1...10 {

let tripleNumber = number * 3 if tripleNumber % 6 == 0 { result += [tripleNumber] } } ղ౴ྫ2ʣએݴܕϓϩάϥϛϯάʢதͰ΋ؔ਺ܕʣ let result = (1...10).map { \$0 * 3 }.filter { \$0 % 6 == 0 }
12. ### ໋ྩܕ ! એݴܕ " ண໨ How ʢखଓ͖ʣ What ʢग़ྗͷੑ࣭ʣ ߏ଄

forϧʔϓ/৚݅෼ذ Λଟ༻ ؔ਺Λܨ͛Δ ʢؔ਺ܕʣ ঢ়ଶͷมߋ varʢεςʔτϑϧʣ letʢεςʔτϨεʣ

19. ### Observable • ΠϕϯτͷྲྀΕʢετϦʔϜʣ • ઒ʹྫ͑ΒΕΔ • ྲྀΕͯ͘ΔΠϕϯτ͸3छྨ͚ͩ • nextʢͳʹ͔ͷ஋ʣ •

errorʢΤϥʔऴྃʣ • completedʢ׬ྃʣ

22. ### // Πϝʔδ ---1---2---3---4---|(completed)---> // ίʔυ Observable<Int> .of(1, 2, 3, 4)

// ετϦʔϜΛੜ੒ .subscribe { print(\$0) } // ετϦʔϜΛ؂ࢹ .dispose() // ετϦʔϜΛഁغ

24. ### // Πϝʔδ ---(tap)---(tap)---(tap)---> // ίʔυ button.rx.tap // rx.tap෦෼͕RxCocoaͷ֦ு෦෼ .subscribe {

print("λοϓ͞Ε·ͨ͠") } .dispose()

26. ### // Πϝʔδ ---͋---͍͋---͍͋͏---͍͋͏͑---͍͋͏͓͑---> // ίʔυ textField.rx.text.asObservable() // ೖྗςΩετΛετϦʔϜʹม׵ .map {

String(\$0.count) } // จࣈྻΛจࣈ਺ʹม׵ .bindTo(label.rx.text) // ϥϕϧʹ൓ө .disposed(by: disposeBag)

28. ### // Πϝʔδ --- ! --- " --- # --- !

--- " --- ! ---> filterͰͿͲ͏͚ͩͷετϦʔϜʹม׵͢ΔΑ --- ! --- ! --- ! ---> // ίʔυ Observable<String> .from([" ! ", " " ", " # ", " ! ", " " ", " "]) // ഑ྻ͔ΒετϦʔϜΛੜ੒ .filter( \$0 == " ! ") // ετϦʔϜΛม׵ .subscribe { print(\$0) } .dispose()

30. ### // Πϝʔδ ---Ϩεϙϯε---|(completed)---> ΋͘͠͸ ---×(eror)---> // ίʔυ Observable<T>.create { observer

-> Disposable in // ؔ਺͔ΒετϦʔϜΛੜ੒ APIClient.request() { response in switch response.result { case .success: observer.onNext(response) // nextΛૹ৴ observer.onCompleted() // completedΛૹ৴ case .failure(let error): observer.onError(error) // errorΛૹ৴ } } return Disposables.create() }

35. ### @IBAction func buttonTapped() { label.text = "loading..." apiRequest() } func

apiRequest() { userInfoModel.request { [weak self] result in switch result { case .success(let userInfo): self?.repositoryListModel.request(userId: userInfo.userId) { result in switch result { case .success(let repositoryList): self?.label.text = repositoryList.map { \$0.title }.joined(separator: "\n") case .failure(let error): print(error) } } case .failure(let error): print(error) } } }

38. ### func rxRequest(api: API) -> Observable<T> { return Observable<T>.create { observer

-> Disposable in Alamofire.request(api.urlString, method: api.method, parameters: api.parameters) .validate(statusCode: 200..<300) .responseJSON { response in switch response.result { case .success: do { guard let jsonData = response.data else { observer.onError(APIClientError.emptyResponseError) return } let jsonDecoder = JSONDecoder() jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase let data = try jsonDecoder.decode(T.self, from: jsonData) observer.onNext(data) observer.onCompleted() } catch { observer.onError(APIClientError.parseError(error)) } case .failure(let error): observer.onError(APIClientError.connectionError(error)) } } return Disposables.create() } }
39. ### struct UserInfoModel { typealias ResponseType = UserInfo private let apiClient:

APIClient<ResponseType> init(apiClient: APIClient<ResponseType> = APIClient()) { self.apiClient = apiClient } func request(completion: @escaping (Result<ResponseType>) -> Void) { apiClient.request(api: .userInfo) { result in completion(result) } } func rxRequest() -> Observable<ResponseType> { return apiClient.rxRequest(api: .userInfo) } }

41. ### rxRequestButton.rx.tap .do(onNext: { _ in self.label.text = "loading..." }) .flatMap

{ self.userInfoModel.rxRequest() } .flatMap { self.repositoryListModel.rxRequest(userId: \$0.userId) } .map { \$0.map { \$0.title }.joined(separator: "\n") } .catchErrorJustReturn("Τϥʔ") .bind(to: self.label.rx.text) .disposed(by: disposeBag)

46. ### ΑΓৄ͘͠ • Reactive Programming with Swift 4 • ReactiveX/RxSwift -

Documentation