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