LoginSignup
5
6

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-07-26

はじめに

SwiftでAPIを叩いてサーバーから情報を取得する方法を解説していきます。
後半にはサンプルコードを記載しています。

この記事の対象者

・iOSアプリからAPIを叩いてサーバーから情報を取得する方法を知りたい方
・APIを叩いて情報を取得するサンプルコードが欲しい方

開発環境

・Swift5
・Xcode 13.4.1
・iOS  15

解説手順

1、今回取得する施設データ(JSON形式)
2、サーバーから取得した情報を格納するクラスを作成
3、サーバーにリクエストを送信しレスポンスを受信
4、サンプルコード

1、今回取得する施設データ(JSON形式)

こちらが今回APIから取得するJSON形式のデータです。

//サーバーにある施設情報(仮)
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"}]}

2、サーバーから取得した情報を格納するクラスを作成

全ての変数をイニシャライズしてすぐに使用可能にする

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
        
    }
}

3、サーバーにリクエストを送信

①API通信先のURLを指定してURLRequest型に変換

// 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場合

//GET
request.httpMethod = "Get"

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

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

リクエストがPOST、PUTの場合はhttpbody にdataを代入する

//クエリデータの作成
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でサーバーにアクセス

サーバーにアクセスしてレスポンスを実際に受信していきます
(このコードはコピペですぐに使えます)

//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()

4、サンプルコード

コピペですぐに実装できますが、プロパティや変数等は書き換えて使用してください。

// 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通信を実装しました。
次回は汎用性も高くオブジェクト指向で実装しましたので、ご覧いただければと思います。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6