GASをAPIサーバーとして、iOSアプリから直接スプレッドシートのデータを取得してみる

# 初めに

この投稿ではRPA開発として、以下のユースケースの掛け合わせを想定しています。

- スプレッドシートをGAS(Google App Script)から操作したい
- GASのウェブアプリケーション機能をAPIサーバーとして、iOSアプリから直接リクエストしたい

わざわざ直接iOSからGASへリクエストしなくても、ExtensionAPIのiOS版や、GASでFirebaseやDynamoDBに書き出した後にmBaaSとして、データをリクエストする方がiOSアプリの品質として良いことは間違いありません。
ただRPAの出面としてiOSアプリを採用する一連として紹介します。

![EvangVD-Architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168714/d1ddf894-caad-aa7f-5bbf-8d7de8055286.png)


# スプレッドシート

今回例で用いるスプレッドシートは、私が普段頭を悩ませている、ウェアラブルデバイスでセンシング出来るセンサーデータの一覧です。
以下の画像のD,E,F,G,H列を用いて、**理解度測定の確認テストを行うためのアプリ** を作成することを想定します。

<img width="1286" alt="スクリーンショット 2020-01-28 23.38.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168714/2cc4b430-f054-f82c-3985-d503a53e2bba.png">

# GAS ソースコード

D列〜H列をサンプルで８個取得してみます。
それぞれを `id` , `name` , `nameJP` , `description` , `usage` としてJSONにマッピングしていきます。
8個のJSONレコードを配列にして返す設計とします。
GASの使用上、配列形式で返せるAPIフォーマットがないため、 `{'vitals': getVitalDatas()}` でJSON形式にラッピングして値をiOSアプリに渡します。

GASのウェブアプリ公開については [こちら](https://curiouslead.com/?p=86(%E6%96%B0%E3%81%97%E3%81%84%E3%82%BF%E3%83%96%E3%81%A7%E9%96%8B%E3%81%8F)) が参考になると思います。

```api.gs
function getVitalDatas() {
  var spreadsheetId = '1E6************lgY';
  var rangeName = 'sensorList!D3:H10';
  var values = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeName).values;
  if (!values) {
    Logger.log('No data found.');
  } else {
    var resultArray = [];
    for (var row = 0; row < values.length; row++) {
      var jsonRecord = {
        'id': values[row][0],
        'name': values[row][1],
        'nameJP': values[row][2],
        'description': values[row][3],
        'usage': values[row][4]
      }
      resultArray.push(jsonRecord);
    }
    return resultArray;
  }
}

function doGet(e){
    var result = JSON.stringify({'vitals': getVitalDatas()});
    return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
```

# Swift ソースコード

受け側として `Vital` 型とそれをラッピングした `Result` 型を定義しています。
Result型にデコードした値をvitalsとして、問題なく取得出来たことを確認します。

```APIRequest.swift
import Foundation

struct APIRequest {

    static let mainAPIHost: String = "https://script.google.com/macros/s/AKf****************swg/exec"
    
    static func getSheetData(){
                
        var request = URLRequest(url: URL(string: mainAPIHost)!)
        request.httpMethod = "GET"
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let jsonData = data else { return }

            struct Result: Codable {
                var vitals: [Vital]
            }
          
            do {
                let vitals = try JSONDecoder().decode(Result.self, from: jsonData)
                print(vitals)
            } catch {
                print(error.localizedDescription)
            }
        }
        task.resume()
    }
}

struct Vital: Codable {
    var id: String
    var name: String
    var nameJP: String
    var description: String
    var usage: String
}
```

# iOSアプリ側でデータ取得の確認

デバッグログ画面に、Vital型形式にマッピングされ、それを配列とするResult型を取得出来ていることが確認できます。

<img width="1397" alt="スクリーンショット 2020-01-28 23.57.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168714/f279b8a7-a792-64c9-a94c-4d0df45ae3f5.png">


# 終わりに

このアプリは `EvangVitalData` として後日AppStoreに公開する予定です。
生体データの確認テストが出来るので、もし見かけたら遊んでみてください。