iOSアプリ開発の初心者向けに、Google Apps Script(GAS)のデータをJSON形式で取得してiPhone上に表示させるやり方について解説します。
本記事では以下の内容が学べます。
・GASのスクリプトエディタの使い方
・GASをWebアプリとして使用する方法
・JSON形式をResponseオブジェクトに変換
・GASから取得した配列からデータをリスト形式で表示
本記事では中身を簡単にするため、取得するデータを一つにしていますが、GAS側でコードを付け加えれば連続したデータを取得できるような仕様にしています。
作成するiOSアプリ
GASに入力したデータを取得してiPhone上にリスト形式で表示するシンプルなアプリです。
{"results":[{"id":1,"内容":"テスト"}]}
JSON形式ではこのようなデータ形式にしたものをSwift側で取り扱っていきます。
開発環境
Xcode Version 12.5 (12E262)
Apple Watch Ver.7.4.1(18T201)
iPhone X Ver.14.5.1
GASでコードを書く
新しいスプレッドシートを開いて以下のように入力しておきます。
次にスクリプトエディタを開きます。
以下のコードを入力します。
resultというIDと内容データを格納したリストを定義して、JSON形式で出力するマクロです。
function doGet(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('シート1');
var number = sheet1.getRange("A2").getValue();
var contents = sheet1.getRange("B2").getValue();
let result = {"results":[
{"id":number, "value":contents}
]};
var out = ContentService.createTextOutput();
out.setMimeType(ContentService.MimeType.JSON);
out.setContent(JSON.stringify(result));
return out;
}
入力が終わったらデプロイボタンを押し、ウェブアプリとしてデプロイします。
その際、セキュリティ上の注意画面が表示された場合は写真の順序で進めていけば大丈夫です。
説明とアクセスできるユーザー(今回はSwiftからアクセスできるように全員にしました)を選択してデプロイボタンを押します。
※全員にした場合、URLをネット上に公開してしまうと誰でもアクセスできるようになってしまうので注意してください
ウェブアプリ用のURLが表示されるのでコピーして次に解説するSwiftコードに貼り付けられるようにしておきます。
GAS側の解説は以上です。
Xcodeでコードを書く
Xcodeで新規プロジェクトの作り方が分からない方はまずはこちらの記事を読んでください。
GASで使用した変数を定義する部分
SwiftUIをインポートし、ResponseとResultと呼ぶデータを格納する構造体を定義します。
GAS内で定義している、今回のアプリに必要な項目をSwift側でも定義します。
import SwiftUI
/// GASから取得する戻り値の型
struct Response: Codable {
var results: [Result] // GASで定義
}
/// 個々の情報の型
struct Result: Codable {
var id: Int // GASで定義
var value: String? //GASで定義
}
JSON形式をResponseオブジェクトに変換する部分
func loadData()でJSON形式をSwiftで扱えるように変換を行います。
●●●の部分にGASで取得したURLを貼り付けます。
func loadData() {
/// URLの生成
let urlString = "●●●".addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
guard let url = URL(string: urlString!) else {
/// 文字列が有効なURLでない場合の処理
return
}
/// URLリクエストの生成
let request = URLRequest(url: url)
/// URLにアクセス
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data { ///データ取得チェック
///JSON形式をResponseオブジェクトに変換
let decoder = JSONDecoder()
guard let decodedResponse = try? decoder.decode(Response.self, from: data) else {
print("Json decode エラー")
return
}
///情報をUIに適用
DispatchQueue.main.async {
results = decodedResponse.results
}
} else {
/// データが取得できなかった場合の処理
print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
}
}.resume()
}
ContetViewの部分
VStackを使用してNavigationViewとGASから取得した全てのidのデータ(今回は一つ)を並べたリストを縦方向に整列させて表示させます。
struct ContentView: View {
@State private var item = ""
@State private var results = [Result]() /// 空の配列を生成
var body: some View {
VStack{
NavigationView {
VStack{
List(results, id: \.id) { item in
VStack(alignment: .leading) {
Text(item.value ?? "")
}
}.navigationTitle("内容")
}
}.onAppear(perform: loadData) /// データ読み込み処理
}
}
}
Swift側のコード紹介は以上です。
コード.gs
function doGet(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('シート1');
var number = sheet1.getRange("A2").getValue();
var contents = sheet1.getRange("B2").getValue();
let result = {"results":[
{"id":number, "value":contents}
]};
var out = ContentService.createTextOutput();
out.setMimeType(ContentService.MimeType.JSON);
out.setContent(JSON.stringify(result));
return out;
}
ContentView.swift
//
// ContentView.swift
//
//
// Created on 2021/05/31.
//
import SwiftUI
/// GASから取得する戻り値の型
struct Response: Codable {
var results: [Result]
}
/// 個々の情報の型
struct Result: Codable {
var id: Int // GASで定義
var value: String? //GASで定義
}
struct ContentView: View {
@State private var item = ""
@State private var results = [Result]() /// 空の配列を生成
var body: some View {
VStack{
NavigationView {
VStack{
List(results, id: \.id) { item in
VStack(alignment: .leading) {
Text(item.value ?? "")
}
}.navigationTitle("内容")
}
}.onAppear(perform: loadData) /// データ読み込み処理
}
}
/// データ読み込み処理
func loadData() {
/// URLの生成
let urlString = "●●●".addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
guard let url = URL(string: urlString!) else {
/// 文字列が有効なURLでない場合の処理
return
}
/// URLリクエストの生成
let request = URLRequest(url: url)
/// URLにアクセス
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data { ///データ取得チェック
///JSON形式をResponseオブジェクトに変換
let decoder = JSONDecoder()
guard let decodedResponse = try? decoder.decode(Response.self, from: data) else {
print("Json decode エラー")
return
}
///情報をUIに適用
DispatchQueue.main.async {
results = decodedResponse.results
}
} else {
/// データが取得できなかった場合の処理
print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
}
}.resume()
}
}
参考サイト
https://capibara1969.com/2946/