LoginSignup
1
1

#14 Airtableを利用してiOSアプリを開発する

Posted at

今回は、以前作成した地図クイズアプリを基に発展させて行います。このアプリはAirtableからデータを取得し、UITableViewに地図の名称と画像を表示します。ネットワークリクエストにはURLSessionを使用し、サードパーティライブラリのKingfisherを使ってネットワーク画像を読み込みます。

Simulator Screen Recording - iPhone 15 Pro - 2024-05-20 at 16.52.57.gif

Airtableデータベースの設定

まず、Airtableでデータベース(ベース)を作成し、必要なテーブルとフィールドを追加しました。この例では、mapInfoという名前のテーブルがあり、以下のフィールドを含んでいます:

areaName:エリアの名称
areaInfo:エリアの情報(例:紹介リンク)
areaImage:エリアの画像(添付ファイルタイプ)

airtable.png

データ構造の定義

Airtableのデータ構造に対応するSwift構造体を定義します。Struct.swiftという名前のファイルを作成します:

import Foundation

struct MapInfo: Codable {
    let records: [Record]
}

struct Record: Codable {
    let id, createdTime: String
    let fields: Fields
}

struct Fields: Codable {
    let areaImage: [AreaImage]
    let areaInfo: String
    let areaName: String
}

struct AreaImage: Codable {
    let id: String
    let width, height: Int
    let url: String
    let filename: String
}

Airtable APIの実装

Airtableからデータを取得し、それをMapInfo構造体にデコードする必要があります。NetworkManager.swiftという名前のファイルを作成します:

import Foundation

let apiKey = APIKey.default
var mapInfoData: MapInfo?

func fetchData(completion: @escaping (MapInfo?) -> Void) {
    if let url = URL(string: "https://api.airtable.com/v0/app1MfmI8sP5PmaSp/mapInfo") {
        var request = URLRequest(url: url)
        // 認証ヘッダーを設定
        request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
        
        // HTTPリクエストを送信
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data {
                // JSONデータを印刷
                let decoder = JSONDecoder()
                do {
                    // JSONデータをMapInfo構造体にデコード
                    let result = try decoder.decode(MapInfo.self, from: data)
                    mapInfoData = result // デコード結果をグローバル変数に保存
                    completion(result) // 完了クロージャを呼び出し
                } catch {
                    print(error)
                    completion(nil) // デコードに失敗した場合、nilを返す
                }
            } else if let error {
                print(error)
                completion(nil) // リクエストが失敗した場合、nilを返す
            }
        }.resume()
    }
}

TableViewの設定

次に、Airtableから取得したデータを表示するためにUITableViewを設定します。MapInfoTableViewController.swiftという名前のファイルを作成します:

import UIKit
import Kingfisher

class MapInfoTableViewController: UITableViewController {
    var mapInfoData: MapInfo?

    override func viewDidLoad() {
        super.viewDidLoad()
        fetchData { data in
            DispatchQueue.main.async {
                if let data = data {
                    // データを他の処理に使用
                    self.mapInfoData = data
                    self.tableView.reloadData() // テーブルビューを再読み込み
                } else {
                    // データ読み込み失敗の処理
                    let alert = UIAlertController(title: "Error", message: "Failed to load data", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                    self.present(alert, animated: true, completion: nil)
                }
            }
        }
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return mapInfoData?.records.count ?? 0
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MapInfoTableViewCell", for: indexPath) as! MapInfoTableViewCell

        if let record = mapInfoData?.records[indexPath.row] {
            cell.mapName.text = record.fields.areaName
            cell.url = record.fields.areaInfo
            
            if let url = record.fields.areaImage.first?.url {
                cell.mapImage.kf.setImage(with: URL(string: url))
            }
        }
        return cell
    }
}

TableViewセルの設定

MapInfoTableViewCell.swiftという名前のファイルを作成します:

import UIKit
import SafariServices

class MapInfoTableViewCell: UITableViewCell, SFSafariViewControllerDelegate {

    @IBOutlet weak var mapName: UILabel!
    @IBOutlet weak var mapImage: UIImageView!
    var url: String?

    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

    func openUrl() {
        guard let urlString = url, let url = URL(string: urlString) else { return }
        let safariVC = SFSafariViewController(url: url)
        safariVC.delegate = self
        UIViewController().present(safariVC, animated: true, completion: nil)
    }
}

結語

このアプリを通して、Airtable APIと連携して地図情報を取得し、それをTableViewに表示する方法を学びました。また、Kingfisherライブラリを利用してネットワーク画像を読み込む方法も学びました。さらに、TableViewのデリゲートとデータソースを設定し、データの表示と管理を実現しました。次に、APIのリンクをボタンにしてSafariで表示することに挑戦したいと思います。

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