swiftでwebAPIを呼び出してjsonデータを表示させる


概要

 この記事は初心者の自分がRESTfulなAPIとswiftでiPhone向けのクーポン配信サービスを開発した手順を順番に記事にしています。技術要素を1つずつ調べながら実装したため、とても遠回りな実装となっています。

 前回のJSON形式でレスポンスをするwebAPIを作成するで(モックアップのレベルですが)リクエストパラメータで指定した番号のクーポン情報をjson形式でレスポンスするクーポン配信APIができたので、リクエストする側のアプリをSwiftで実装します。

今回は

  1. アプリからwebAPIにリクエストを投げる
  2. レスポンスされた情報をjson形式でコンソールに表示する

の流れを一旦完成させ、アプリ画面にクーポンを表示する下準備をしようと思います。

参考

環境

Mac OS 10.15
Swift5
Xcode11.1

アプリの仕様

  • アプリ起動時にAPIにリクエストし、レスポンスされたクーポン情報をjson形式でコンソールに表示する。
  • webAPIにリクエストする際、リクエストパラメータとしてクーポンコードを指定する。

手順

  • Xcodeでクライアントアプリ側のプロジェクトを作成
  • http通信を許可する設定をする
  • webAPIとの通信部分をswiftで実装
  • webAPIから受け取った情報を画面に表示する処理を実装
  • 動作確認

Xcodeでクライアントアプリ側のプロジェクトを作成

現在、SwiftUIがリリースされていますが、今回は多少経験のある従来のstoryboadを使います。

Xcodeを開いて、「Create a new Xcode project」を選択。

次の画面で、iOS の Single View App を選択。

次の画面でプロジェクトのオプションを設定。
この時、User Interface: は SwiftUI ではなく Storyboardを選択します。Product Name: や Team: Organization Name: などはご自身の設定を入れてください。

http通信を許可する設定をする

参考にさせて頂いたサイトで紹介されている手順に従い、Info.plist ファイルを編集して http通信を許可します。

webAPIとの通信部分をswiftで実装

とりあえず、swift側で 前回までに作成したクーポン配信APIを呼び出して、レスポンスを得られるところまで作成します。

swiftのViewController.swiftを下記の通り実装します。
Apiから取得する data、response、error の中身をコンソールに出力する事でswift側でapiのレスポンスを得られたか判断します。APIへのリクエストURLはコードにベタがきします。

ViewController.swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // アプリがロードされた時に実行させたい処理を書きます

        let url: URL = URL(string: "http://127.0.0.1:8000/coupon/?coupon_code=0001")!
        let task: URLSessionTask = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
            // コンソールに出力           
            print("data: \(String(describing: data))")
            print("response: \(String(describing: response))")
            print("error: \(String(describing: error))")
        })
        task.resume()        
    }
}

djangoのサーバを起動してクーポン配信APIを立ち上げたら、Xcodeでプログラムを実行してみます。iPhoneのシミュレータが起動しアプリの画面が開いたらXcodeのコンソール出力を確認します。画面には何も表示設定をしていないのでただの白い画面です。

Xcodeのコンソール出力を見るとdata、response、error の内容が出力されているので、レスポンスを得られていることを確認出来ました。

django のサーバを起動したターミナルを確認すると、GETでリクエストを受けていることを確認できます。

レスポンスで受け取ったdataをswift側でJSONに変換する

APIとの疎通まで確認出来ましたので、次はレスポンスされたデータから情報を取り出すために、data型をJSONに変換する処理を追加します。

URLSessionTaskのクロージャー部分にJSONに変換するためのコードを追加します。クロージャーに関する解説は参考にさせて頂いた記事をご覧ください。

ViewController.swift のURLSessionTaskの部分に、print([json形式の変数])を入れて、JSONに変換出来たか確認します。

ViewController.swift
       do{
                let couponData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)
                print(couponData) // Jsonの中身を表示
            }
            catch {
                print(error)
            }

djangoのサーバが起動中なのを確認してswiftを実行し、コンソール出力を見ます。コンソール出力にjsonの中身が表示されているので変換は成功です。

jsonの中身は見れましたが、coupon_benefitsの部分が よく分からない文字列("1000\U5186\U5f15\U304d\U30af\U30fc\U30dd\U30f3\Uff01”)になっています。
これを本来の文字列にするには、jsonのパースが必要です。

jsonをパースする

data型をjsonに変換しただけだとANY型になっており、上記のようによく分からない文字列で表示されてしまいます。なので、ANY型をString型にキャストする必要があります。

let couponData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)

の後ろに、as! [String: Any] を付けます。

let couponData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! [String: Any]

djangoのサーバが起動中なのを確認してアプリを実行し、コンソール出力を見るます。
"coupon_benefits": 1000円引きクーポン!になっているのでパース成功です。

下記のコードは不要になったので削除します。

print("data: \(String(describing: data))")
print("response: \(String(describing: response))")
print("error: \(String(describing: error))")

以上でアプリの画面にapiで取得した情報を表示する準備が出来ました。