（超簡単）SwiftでAPIを叩いてサーバーから情報を取得する方法　

# はじめに
SwiftでAPIを叩いてサーバーから情報を取得する方法を解説していきます。
後半にはサンプルコードを記載しています。
# この記事の対象者
・iOSアプリからAPIを叩いてサーバーから情報を取得する方法を知りたい方
・APIを叩いて情報を取得するサンプルコードが欲しい方
# 開発環境
・Swift５
・Xcode　13.4.1
・iOS　　15
# 解説手順
１、今回取得する施設データ（JSON形式）
２、サーバーから取得した情報を格納するクラスを作成
３、サーバーにリクエストを送信しレスポンスを受信
４、サンプルコード
## １、今回取得する施設データ（JSON形式）
こちらが今回APIから取得するJSON形式のデータです。
```swift
//サーバーにある施設情報(仮)
let homeData_json = {“status”:true,”homes”:[{“homeId”:”4”,”homeName”:”A施設_1ち”,”homeType”:”2","homeImage":"/img/s-study.png"},
{"homeId":"10","homeName":""B施設_1","homeType":"4","homeImage":"/img/s-speech.png"},{"homeId":"11","homeName":""B施設_2園","homeType":"4","homeImage":"/img/s-speech.png"},
{"homeId":"12","homeName":""B施設_3","homeType":"4","homeImage":"/img/s-speech.png"},{"homeId":"9","homeName":""C施設_1","homeType":"3","homeImage":"/img/s-switch.png"},
{"homeId":"7","homeName":""C施設_2","homeType":"3","homeImage":"/img/s-switch.png"},{"homeId":"8","homeName":""D施設_4園","homeType":"3","homeImage":"/img/s-switch.png"}]}

```
## ２、サーバーから取得した情報を格納するクラスを作成
全ての変数をイニシャライズしてすぐに使用可能にする
```swift
import Foundation
class FacilityData{
    
    var homeId : Int!
    var homeImage : String!
    var homeName : String!
    var homeType : Int!
    //イニシャライズ
    init(homeId : Int,homeImage : String, homeName : String , homeType : Int){
        self.homeId = homeId
        self.homeImage = homeImage
        self.homeName = homeName
        self.homeType = homeType
        
    }
}
```
## ３、サーバーにリクエストを送信
###  ①API通信先のURLを指定してURLRequest型に変換
```swift
// API call
//端末のUUIDを取得する
let uuid = UIDevice.current.identifierForVendor!.uuidString
//APIを叩く先のURL
//connectURLは共通のAPI通信先のURL　　
let apiURL = connectURL + "/api/ios/homes/?terminalId=" + uuid
//apiURLをURl型に変換する
guard let url = URL(string: apiURL) else { return }
//URLRequest型に変換
var request = URLRequest(url: url)
```

### ②リクエストのプロパティを記入
リクエストがGET場合
```swift
//GET
request.httpMethod = "Get"

//"application/x-www-form-urlencoded"はエンコードの種類

request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

```
リクエストがPOST、PUTの場合はhttpbody にdataを代入する
```swift
//クエリデータの作成
let data : Data = "terminalId=\(terminalId)".data(using: .utf8)!
request.httpBody = data
```
GET：主に送受信用です。送信するデータを直接URLに記入するので、見えてもいいデータの場合に使う。（セキュリティ的に良くない場合がある）

POST：主に送受信用です。request.httpbodyに送信するデータをData型で代入するのでセキュリティに長けている。（POSTの方が多いような気がする）

PUT：主に送信用です。request.httpbodyに送信するデータをData型で代入し、指定したURLにデータを送信します。（画像アップロードなど）

リクエストの種類：.httpMethodで指定する（GET,POST,PUT）
エンコードの種類：.setValueで指定する

### ③URLSessionでサーバーにアクセス
サーバーにアクセスしてレスポンスを実際に受信していきます
（このコードはコピペですぐに使えます）
```swift
//URLSessionでサーバーにアクセス
URLSession.shared.dataTask(with: request) {(data, response, error) in
    
    if let error = error {
        print("Failed to get item info: \(error)")
        return;
    }
    
    if let response = response as? HTTPURLResponse {
        if !(200...299).contains(response.statusCode) {
            print("Response status code does not indicate success: \(response.statusCode)")
            return
        }
    }
    
    if let data = data {
        do {
            //jsonDictはサーバーにある情報をJSON形式で取得
            let jsonDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
            
            let status = jsonDict!["status"] as! Bool
            print("status:\(status)")
            
            //var homes : Int!
            if(status == true){
                //非同期通信
                DispatchQueue.main.async {
                    //["homes"]の中にあるデータ全て（二次元配列）をhomesWArrayに入れる
                    let homesWArray = jsonDict!["homes"] as! [[String: Any]]
                    var homeCount = 0
                    for home in homesWArray {
                        var homeId_String: String! = home["homeId"] as? String ?? ""
                        
                        let homeId = Int(homeId_String)
                        let homeName: String! = home["homeName"] as? String ?? ""
                        var homeImage_url: String! = home["homeImage"] as? String ?? ""
                        var homeType_String : String! = home["homeType"] as? String ?? ""
                        let homeType = Int(homeType_String)
                        
                        
                        var image:UIImage!
                        
                        if(homeImage_url == ""){
                            image = UIImage(named:"subaco_def_icon")
                        }
                        else{
                            homeImage_url = connectURL + homeImage_url!
                            image = UIImage(url:homeImage_url!)
                            
                        }
                        //取得したデータを配列に追加していく
                        self.homeIDArray.append(homeId!)
                        self.homeImageNameArray.append(image!)
                        self.homeNameArray.append(homeName!)
                        self.homeTypeArray.append(homeType!)
                      //FacilityDataクラスのような複数のデータを格納するモデルクラスを作成
                        //取得した施設情報(homeId、image、homeName、homeType)をさらに配列に追加していく
                        self.facilityInfoArray.append(FacilityData(homeId: homeId!, homeImage: homeImage_url, homeName: homeName, homeType: homeType!))
                        homeCount += 1
                    }//for homesWArray
                    //APiから情報を取得したらここでTableViewなどを更新する
                    
                }//main
            }// if status = true
            else {
            }
        } catch {
            print("Error parsing the response.")
        }
    } else {
        print("Unexpected error.")
    }
}.resume()
```
## ４、サンプルコード
コピペですぐに実装できますが、プロパティや変数等は書き換えて使用してください。
```swift
// API call
// ①API通信先のURLを指定してURLRequest型に変換
let uuid = UIDevice.current.identifierForVendor!.uuidString
//APIを叩く先のURL
//connectURLは共通のAPI通信先のURL　　
let apiURL = connectURL + "/api/ios/homes/?terminalId=" + uuid
//apiURLをURl型に変換する
guard let url = URL(string: apiURL) else { return }

var request = URLRequest(url: url)
// ②リクエストのプロパティを記入
request.httpMethod = "Get"
//"application/x-www-form-urlencoded"はエンコードの種類
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
//POST、PUTの場合
//クエリデータの作成
//let data : Data = "terminalId=\(terminalId)".data(using: .utf8)!
//request.httpBody = data

//URLSessionでサーバーにアクセス
URLSession.shared.dataTask(with: request) {(data, response, error) in
    
    if let error = error {
        print("Failed to get item info: \(error)")
        return;
    }
    
    if let response = response as? HTTPURLResponse {
        if !(200...299).contains(response.statusCode) {
            print("Response status code does not indicate success: \(response.statusCode)")
            return
        }
    }
    
    if let data = data {
        do {
            //jsonDictはサーバーにある情報をjson型で取得
            let jsonDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
            
            let status = jsonDict!["status"] as! Bool
            print("status:\(status)")
            
            //var homes : Int!
            if(status == true){
                //非同期通信
                DispatchQueue.main.async {
                    //["homes"]の中にあるデータ全て（二次元配列）をhomesWArrayに入れる
                    let homesWArray = jsonDict!["homes"] as! [[String: Any]]
                    var homeCount = 0
                    for home in homesWArray {
                        var homeId_String: String! = home["homeId"] as? String ?? ""
                        
                        let homeId = Int(homeId_String)
                        let homeName: String! = home["homeName"] as? String ?? ""
                        var homeImage_url: String! = home["homeImage"] as? String ?? ""
                        var homeType_String : String! = home["homeType"] as? String ?? ""
                        let homeType = Int(homeType_String)
                        
                        
                        var image:UIImage!
                        
                        if(homeImage_url == ""){
                            image = UIImage(named:"subaco_def_icon")
                        }
                        else{
                            homeImage_url = connectURL + homeImage_url!
                            image = UIImage(url:homeImage_url!)
                            
                        }
                        //取得したデータを配列に追加していく
                        self.homeIDArray.append(homeId!)
                        self.homeImageNameArray.append(image!)
                        self.homeNameArray.append(homeName!)
                        self.homeTypeArray.append(homeType!)
                      //FacilityDataクラスのような複数のデータを格納するモデルクラスを作成
                        //取得した施設情報(homeId、image、homeName、homeType)をさらに配列に追加していく
                        self.facilityInfoArray.append(FacilityData(homeId: homeId!, homeImage: homeImage_url, homeName: homeName, homeType: homeType!))
                        homeCount += 1
                    }//for homesWArray
                    //APiから情報を取得したらここでTableViewなどを更新する
                    
                }//main
            }// if status = true
            else {
            }
        } catch {
            print("Error parsing the response.")
        }
    } else {
        print("Unexpected error.")
    }
}.resume()

```
# 終わりに
最後まで見て頂きありがとうございました。
今回は簡易的にAPI通信を実装しました。
次回は汎用性も高くオブジェクト指向で実装しましたので、ご覧いただければと思います。