Alamofireを使用したAPI通信について（MVC）

初めまして！！
休学をしてプログラミングを学んでいるりゅーちゃんです！！
今回はアドベントカレンダーの３日目を担当します！:bow_tone1:
題名にも記載しているように今回はAlamofireについて解説していきます:clap:
（自分自身まだ初学者なのでどんどんFBしてくださると助かります！！ただ優しくしていただけると幸いです:pray:）

##Alamofireについて:relaxed:（今回の記事の概要）

#####言わずともしれたAPI通信を行う際の優秀なライブラリです！！
（APIKitとは何が違うのか？については知識不足でまだわかっていません:cold_sweat:）
Qiitaの記事も豊富で学習がしやすく、ドキュメントを参照すればすぐに使うことができ初心者にも優しいものです！！:joy:

######ではなぜ今回は改めて記事を書う理由は。。。
- MVCを採用した際のデーターの渡し方の説明が少ない記事が多い（Alamofireの使い方に重点をおいているため）
- 大まかな情報の流れについて記事が難しすぎる
- 自分自身の振り返りのため

この３つの要因があります！！
稚拙な文章ですが最後までお付き合いしてくださると幸いです！！:muscle:

##MVCを利用したAPI通信について（Alamofireを添えて:wine_glass:）
まずは行いたい処理を確認していきます！！:writing_hand:
1. ViewControllerから通信に必要な情報をModelに渡してあげる:eyes:
2. ModelでViewControllerから受け取った情報をheadersに詰め込みAPI通信を行う
3. ViewControllerに取得データを出力する（本来ならTableViewなどに表示するが今回は割愛します:disappointed_relieved:）
大まかに分けてこの３つの処理を実行していきます！！

```json:Sample.json
{
"data": [
        {
            "name": "牛肉",
            "food_type": "meat",
            "rate": 60,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "豚肉",
            "food_type": "meat",
            "rate": 30,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "鶏肉",
            "food_type": "meat",
            "rate": 0,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "鯖",
            "food_type": "fish",
            "rate": 0,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "イワシ",
            "food_type": "fish",
            "rate": 0,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "にんじん",
            "food_type": "vegetable",
            "rate": 30,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "キャベツ",
            "food_type": "vegetable",
            "rate": 100,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "玉ねぎ",
            "food_type": "vegetable",
            "rate": 100,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "じゃがいも",
            "food_type": "vegetable",
            "rate": 100,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        },
        {
            "name": "もやし",
            "food_type": "vegetable",
            "rate": 100,
            "user": {
                "uuid": "2553846F-996A-4D3F-93FC-9ACD8D8CD16B"
            }
        }
    ]
}
```
このJsonデーターを取得しViewで表示するのが今回のゴールです！！
####まずはAPI通信のした準備としてCodableを見ていきましょう:thinking:

```swift:SampleResponse.swift

struct MetaFoodTypes: Codable {
    let data: [FoodTypes]
}

struct FoodTypes: Codable {
    let name: String
    let foodType: String
    var rate: Int
    
//スネークケースをキャメルケースに変換している
    enum CodingKeys: String, CodingKey {
        case name
        case foodType = "food_type"
        case rate
    }
}
```
今回はJSONの形からdataをKeyとしてその中の情報を取得する必要があります！！
そこで上記のようにMetaFoodTypes、FoodTypesを作ることCodableがMetaFoodTypesを見てくれた後にFoodTypesを見る処理を書いています:relaxed:

> https://qiita.com/_ha1f/items/bf1aad5ea3e927f59f9d
今回の説明では不十分だと感じた方はこの方の記事を見るのをお勧めします:punch:

####次はViewControllweです！！

```swift:ViewController.swift

private let model = ViewModel()

private func getFoodTypesdata() {
//userdefaultsの処理については後ほど記述します！！
//tokenを取得しModelに情報を渡してあげる
   guard let token = UserData.token else { return }
        model.getFoodtypes(token: token, handler: { result in
//Modelからの処理の結果がresult部分に渡される
                     print(result)
     })
}
```
####追記：userdefaultsについて
```swift:UserDefault.swift

struct UserData {
    static let userDefault = Foundation.UserDefaults.standard
    
    struct Key {
        static let token = "token"
    }
}

extension UserData {
    static var token: String? {
        get {
            return userDefault.string(forKey: Key.token) ?? nil
        } set {
            userDefault.set(newValue, forKey: Key.token)
            userDefault.synchronize()
        }
    }
}
```
ここの処理についてはまだまだ言語化ができていないため、理解次第この記事を編集していきます:bow_tone2:
(参照した記事がQiitaではないため今回は参照リンクは記載しません。。。)

######最後にViewModelを見ていきましょう！！
```swift:ViewModel.swift

import Foundation
import Alamofire

class SelectViewModel {
 func getFoodTypesdata (token: String, handler: @escaping (MetaFoodTypes) -> Void) {
        
        let url = URL(string: "********************")!
        
        //ここでViewから取得してきた情報を使用している
        let headers: HTTPHeaders = [
            "**********": "********" + token
        ]
        
        AF.request(url, method: .get, encoding: JSONEncoding.default, headers: headers)
            .validate(statusCode: 200..<300)
            .responseJSON{ response in
                switch response.result {
                case .success( _):
                    guard let data = response.data else { return }
                    guard let foodTypes = try? JSONDecoder().decode(MetaFoodTypes.self, from: data) else { return }
             //ここの処理の結果がViewのhandlerに格納される！！
                    handler(foodTypes)
                case .failure(let error):
                    print(error)
                }
        }
    }
}
```
この部分の処理についてはクロージャを使っていること以外はAlamofireのドキュメントを読むことで理解することができました！！
是非とも英語ばかりで読みたくはない（実際に自分がそうでした:sweat_smile:）と思いますが理解度が深くなるので是非ともチャレンジしてください！！

##まとめ
今回は大まかに情報の流れに焦点を当てて記事を書いてみました！！
まだまだ1つ、１つの処理に関しては理解が足りない部分が多いですが勉強を怠らず、強くなっていきたいです:muscle:
間違っているぞ！！、ここはもっと詳しく書いてくれ！！などがありましたら気軽にコメント、編集リクエストしてください:pray:
今後の課題としてはAPI通信部分の共通化について取り組んでいきます！！！
（参考にできるものや、書き方を教えてくださると泣いて喜びます:joy:）

またこんな初学者が諦めずに頑張れているのはTechTrainというサービスを利用し、壁にぶつかるたびにメンターさんに相談することができたからです:angel:
詳しい概要は[TechTrain Advent Calendar 2019 1日目](https://qiita.com/TakumaKurosawa/items/8db598b9c0fcb6b9c2bb)に記載してありますので気になった方はみてみてください！！:wave: