15
20

More than 5 years have passed since last update.

Alamofireで取得したデータをTableViewで表示する

Last updated at Posted at 2018-08-08

3年以上ぶりに、iOSの開発を行い始めた。今の時代はswift4 なのね。

開発環境

OS : MacOS High Sierra Version 10.13.6
Xcode : Version 9.4.1

Server

サーバサイドは、JSONデータをRuby on Railsのように、DBスキーマから簡単に返すことができるので、Elixir言語で書かれた Phoexnix framework を利用しています。
その辺りは、後日に。

取得データ

リクエスト送信先から返ってくるJSONデータは下記の感じ。

{
  "users" : [
    {
      "option" : "システムエンジニア",
      "age" : 46,
      "name" : "田島 啓之",
      "id" : 1
    },
    {
      "option" : "経理",
      "age" : 49,
      "name" : "都築 奏子",
      "id" : 2
    },
    {
      "option" : "ネットワークエンジニア",
      "age" : 45,
      "name" : "中村 栄人",
      "id" : 3
    },
    {
      "option" : "総務",
      "age" : 38,
      "name" : "千葉 博子",
      "id" : 4
    }
  ]
}

ソースコード解説

ListViewController.swiftのコードを説明する。

まずは、必要なライブラリをimportする。ここでは、AlamofireSwiftyJSONを利用する。

import UIKit
import Alamofire
import SwiftyJSON

次に、Swift4から、Codableというもので、構造体とJSONデータを簡単にマッピングできるようになったらしいので、Codableを利用して下記のような構造体を定義する。
これは、JSONデータのネスト構造を見てわかるように、Users構造体の中に、User構造体のリストが定義されている構造となる。

struct User : Codable{
    let id : Int
    let name: String
    let age : Int
    let option : String
}
struct Users : Codable{
    let users : [User]
}

ListViewControllerクラスは、UITableViewDelegateUITableViewDataSourceを採用する。特に問題はない。

class ListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

各メソッドから参照可能なように、Users構造体を定義する。初期化時には値が決まらないため、nilを許すため、オプショナル型としている。

    var users : Users?

viewDidLoad()においてUIの初期化を行う。

    override func viewDidLoad() {
        super.viewDidLoad()

        let tableView : UITableView!
        tableView = UITableView(frame: view.frame, style: .grouped)
        tableView.delegate = self
        tableView.dataSource = self

        view.addSubview(tableView)

Alamofireの主要処理部分。まずは、対象サーバへリクエストを送信して、JSONで受け取る。レスポンスがnilの場合は、そのままreturn

レスポンスがnilでない場合は、JSONDecoderで、Users構造体へマッピングする。

tableView.reloadData()は、Alamofireで取得するデータは非同期のため、初回は、tableViewは空のため、読み込みが完了した時点で、tableViewをリロードする必要がある。

        //Alamofire
        Alamofire.request("http://localhost:4000/user")
            .responseJSON{res in
                guard let json = res.data else{
                    return
                }
                self.users = try! JSONDecoder().decode(Users.self, from: json)

            tableView.reloadData()
        }

ここでは、リストの数を返す必要がある。通信が非同期のため、この時点では構造体はnilなので、初回は0を返す必要がある。リロードされた時に、Users構造体にデータはセットされているので、users.count でデータ数が取得できる。

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let cnt = self.users?.users.count{
            return cnt
        }
        return 0
    }

ここでは、セルのデータを設定している。やはりここも、初回はnilのため、let if で、nilチェックを行っている。
データがあれば、cell.textLabel.text を名前を設定する。

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "CELL")
        if let user = self.users?.users[indexPath.row]{
            cell.textLabel?.text = user.name
        }
        return cell
    }

最後に

ここに記したコードは、初回時のデータ取得から表示までのサンプル的な最低限のコードです。もう少しリファクタリングして、構造を設計する必要がありますが、とりあえず動作原理をシンプルに理解するために記載しました。

間違い等がございましたら、ご指摘願います。

下記、全ソースコードです。

ListViewController.swift
import UIKit
import Alamofire
import SwiftyJSON

struct User : Codable{
    let id : Int
    let name: String
    let age : Int
    let option : String
}
struct Users : Codable{
    let users : [User]
}

class ListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var users : Users?

    override func viewDidLoad() {
        super.viewDidLoad()

        let tableView : UITableView!
        tableView = UITableView(frame: view.frame, style: .grouped)
        tableView.delegate = self
        tableView.dataSource = self

        view.addSubview(tableView)

        //Alamofire
        Alamofire.request("http://localhost:4000/user")
            .responseJSON{res in
                guard let json = res.data else{
                    return
                }
                self.users = try! JSONDecoder().decode(Users.self, from: json)

                //Debug
                print("--- User JSON ---")
                print(JSON(json))
                print("--- User Info ---")
                for user in self.users!.users{
                    print("NAME:" + user.name)
                    print("AGE:" + String(user.age))
                }

            tableView.reloadData()
        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let cnt = self.users?.users.count{
            return cnt
        }
        return 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "CELL")
        if let user = self.users?.users[indexPath.row]{
            cell.textLabel?.text = user.name
        }
        return cell
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

Lovly Swift!!!

15
20
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
15
20