Help us understand the problem. What is going on with this article?

Alamofireを使用したAPI通信について(MVC)

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

Alamofireについて:relaxed:(今回の記事の概要)

言わずともしれたAPI通信を行う際の優秀なライブラリです!!

(APIKitとは何が違うのか?については知識不足でまだわかっていません:cold_sweat:
Qiitaの記事も豊富で学習がしやすく、ドキュメントを参照すればすぐに使うことができ初心者にも優しいものです!!:joy:

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

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

MVCを利用したAPI通信について(Alamofireを添えて:wine_glass:

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

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:

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です!!

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について

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を見ていきましょう!!
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つ、1つの処理に関しては理解が足りない部分が多いですが勉強を怠らず、強くなっていきたいです:muscle:
間違っているぞ!!、ここはもっと詳しく書いてくれ!!などがありましたら気軽にコメント、編集リクエストしてください:pray:
今後の課題としてはAPI通信部分の共通化について取り組んでいきます!!!
(参考にできるものや、書き方を教えてくださると泣いて喜びます:joy:

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした