RxSwift,Alamofire,Alamofire-SwiftyJSON使ってAPI通信してみた

#はじめに
こんにちは、RxSwiftを軽く勉強したので
アウトプットしてみようということで記事を書いております。

#なんで勉強しようと思ったの
RxSwift書けたらかっこよさそうって思っただけです！

#お願い
まずRxSwiftってなんぞやって人は、今の世の中最高に便利なので
インターネットを使って調べるところからお願いします。
わからない語句などがありましたら調べながら読んでいただけると幸いです。

##準備をしましょう
xcodeを開いてプロジェクトを作りましょう。
今回ライブラリを管理にCocoaPodsを使うのでターミナルを開いて対象のディレクトリに移動して
`pod init`をしたらPodfileが生成されるので好きな方法でPodfileを開いて、
今回使うライブラリは

 - RxSwift
 - Alamofire
 - Alamofire-SwiftyJSON

の３つなので

```ruby:Podfile
target 'playRxSwift' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!
  pod 'RxSwift'
  pod 'Alamofire'
  pod 'Alamofire-SwiftyJSON'
  # Pods for playRxSwift

end
```

以上のようにPodfileに追加します
そしたらターミナルで`pod install`とコマンドを打ったらライブラリのインストールが始まります。

##実際にコードを書いていきましょう
まず最初に生成されるViewControllerに

```swift:ViewController.swift
import UIKit
import RxSwift
import Alamofire
import Alamofire_SwiftyJSON

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
```

使いたいライブラリを宣言します
もし`no such module RxSwift`のようなエラーがでたらcmd + bをすれば治ると思います。

次にAPI通信をしてGitHubにある自分のリポジトリを取得する処理を書いていきます。

```swift:ViewController.swift
class ApiRequest {
    
    private let baseUrl: String = "https://api.github.com/users/shuuun/repos"
    
    func getResponse() -> Observable<DataResponse<JSON>> {
        return Observable.create { observer in
            Alamofire.request(self.baseUrl)
                .responseSwiftyJSON { response in
                    print("JSONあげるわ")
                    observer.onNext(response)
                    observer.onCompleted()
            }
            return Disposables.create()
        }
    }
}
```
Alamofireを使ってAPI通信を行う処理を行い、返り値にDataResponse型のJSONを返すObservableを作ります。
Observable.createというのはColdなObservableを作ります。
(Coldというのはsubscribe(購読)されないと動かないObservableです。)
クロージャの引数はObserverType型が渡していて、(コードではobserverという名前で書いてます)
その中にはイベントを通知するメソッドが入っています。


次にAlamofire.request()でapi通信を行います。
クロージャの引数はDataResponse<JSON>型(コードではresponseという名前で書いています。)
responseがきたらobserverの中にあるonNextメソッドを使ってresponseの中身を渡してイベントを通知します。
onComplete()は完了を通知するものです。

これで一旦API通信の処理はおしまいです。

次にViewControllerに戻って処理を書いていきます

```swift:ViewController.swift

import UIKit
import RxSwift
import Alamofire
import SwiftyJSON

class ViewController: UIViewController {
    
    private let apiRequest = ApiRequest()
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        start()
    }
    
    private func getResult() -> Observable<DataResponse<JSON>> {
        return self.apiRequest.getMethod()
    }
    
    private func start() {
        print("始まり")
        getResult()
            .subscribe(
                onNext: { res in
                    if let json: JSON = res.value {
                        self.jsonParse(Json: json)
                    }
            },
                onCompleted: {
                    print("終わり")
            }
            ).disposed(by: disposeBag)
    }
    
    private func jsonParse(Json: JSON) {
        let json = JSON(Json)
        json.forEach{ (_, json) in
            print(json["name"])
            print(json["url"])
        }
    }
}
```

```swift:ViewController.swift
private func getResult() -> Observable<DataResponse<JSON>> {
        return self.apiRequest.getResponse()
}
```
getResultメソッドでは、getResponseメソッドを使ってDataResponse<JSON>型を受け取り、returnしています。

```swift:ViewController.swift
private func start() {
        print("始まり")
        getResult()
            .subscribe(
                onNext: { res in
                    if let json: JSON = res.value {
                        self.jsonParse(Json: json)
                    }
            },
                onCompleted: {
                    print("終わり")
            }
            ).disposed(by: disposeBag)
}
```
startメソッドでは、getResult()をsubscribeすることでgetResult()が動いてapi通信が行われます。

```swift
private let disposeBag = DisposeBag()
.disposed(by: disposeBag)
```
これを使うことで購読する必要がなくなったものを解除することができます。

getResponse()にonNext()があることにより、イベントが発行されクロージャの引数にDataResponse<JSON>型の値が入ってきます。
if letを使うことにより、オプショナル型の変数をアンラップしたjsonを使うことができます。

```swift:ViewController.swift
private func jsonParse(Json: JSON) {
        let json = JSON(Json)
        json.forEach{ (_, json) in
            print(json["name"])
            print(json["url"])
        }
}
```

そのjsonをjsonParseメソッドで引数として受け取り、SwiftyJSONを使って使いたいものだけ取り出しています。


これでコードは以上です。startメソッドをviewDidLoadにて呼び出してみましょう

```
始まり
JSONあげるわ
calculatorApp
https://api.github.com/repos/shuuun/calculatorApp
kaiwa
https://api.github.com/repos/shuuun/kaiwa
LikesTinderSNS
https://api.github.com/repos/shuuun/LikesTinderSNS
MEANtemplate
https://api.github.com/repos/shuuun/MEANtemplate
padthon
https://api.github.com/repos/shuuun/padthon
pixiv-hack
https://api.github.com/repos/shuuun/pixiv-hack
quizApp
https://api.github.com/repos/shuuun/quizApp
終わり

```

結果はこんな感じです。
リポジトリ名とurlが表示されましたね
お疲れ様でした。

##おまけ
今回はロード時にstartメソッドを呼び出していましたが、
例えばボタンを押したらstartメソッドを使いたい場合もあると思います。
Rxを使わなかったらActionでボタンを押したらメソッドを呼び出せばいいですが、
Rx使って書く場合にはRxCocoaというライブラリを使うと簡単に書くことができます。
(RxCocoaというのはUIKitの様々なクラスで使用できるプロパティーをextensionとして定義してくれているものです)
PodfileにRxCocoaを書いて`pod install`しましょう。
適当にアウトレットなどでbuttonを紐付けて

```swift:ViewController.swift
button.rx.tap
    .subscribe( onNext:{[weak self] in
        self?.start()
}).disposed(by: disposeBag)
```
viewDidLoadにこれを追記します。
そうするとボタンのタップを購読して押されたらonNextでイベント発行してstartメソッドを呼び出すことができます。

##終わりに
読んでいただきありがとうございました！！
間違ったこと書いていたら教えていただけると嬉しいです！
アプリを作ってストア公開してみたいのでRxSwift使ってのんびり開発して行こうと思います