概要
以前、iPhoneアプリを作成しました
RenderというサービスでFast APIを構築しました
ということはアプリとAPIサーバーで通信が可能にできるのではと思ったので、試してみることにします
本題
作るものとしては自作アプリを開いて用意された2つのボタンを押すとGETリクエスト・POSTリクエストをrenderで用意したAPIに送るというようなものを想定しています
イメージ図
少し雑ですが3画面作る予定です
GET・POSTリクエスト後の画面からトップ画面に戻るボタンのようなものも作れると良いかもしれませんが、そこは努力目標とします
実装
画面の作成
とりあえず動きをつけたいということで、画面を3個分作成してボタンを押すと画面遷移ができる状態にしたいと思います
画面遷移ができる状態にする
大元となる「〜App」というディレクトリ直下に「〜App.swift」というファイルがあります
このファイルがアプリのエントリーポイントとなり、ナビゲーション構造を管理するコンポーネントとなっています
今回、画面の遷移を実装したいので「NavigationStack」というものを使用して遷移ができるようにします
サンプルコードとしては以下になります
ContentViewの部分がアプリ起動時に表示される画面です
(「ContentView.swift」というファイルが存在しており、そちらの担当になります)
import SwiftUI
@main
struct HelloWorldApp: App {
var body: some Scene {
WindowGroup {
// アプリ全体のルートビューをNavigationStackで囲む
NavigationStack {
ContentView() // アプリが最初に表示する画面
}
}
}
}
トップ画面の作成
画面遷移ができる状態になったので次はトップ画面を作成します
先ほどアプリ起動時のトップ画面はContentView.swiftに担当させたので、対象のファイルを修正します
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
// 画面タイトル
Text("Hello World").padding(.bottom, 50) // 下に余白
// 遷移リンク (ボタンを押すと指定されたViewへ移動)
// Destinationには、次に表示したいViewを指定します
NavigationLink(destination: GetRequestView()) {
Text("GETリクエスト")
.font(.headline)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}.padding(.bottom, 50) // 下に余白
NavigationLink(destination: PostRequestView()) {
Text("POSTリクエスト")
.font(.headline)
.padding()
.background(Color.orange)
.foregroundColor(.white)
.cornerRadius(8)
}
}
// NavigationStack内のViewにタイトルを設定
.navigationTitle("ホーム")
}
}
// プレビュー用のコード (画面の確認用)
#Preview {
ContentView()
}
ざっとコードを貼りましたが、それぞれ次のような役割だと認識しています
- Text
- htmlで言うところの p タグ
- NavigationLink
- ここがボタン押下後にどうするかを決めるコードになります
-
destination
の後ろに遷移したい画面を管理しているファイル名・もしくはView名を記載します
- #Preview
- 言葉の通りXcode内でプレビューができるようにします
ここまでで作りたかった画面が3枚完成しています
(さらにトップ画面に戻るボタン?のようなものもできています)
とりあえずトップ画面をプレビューで表示した時の画像を貼ります
GETリクエストのコード
import SwiftUI
struct GetRequestView: View {
var body: some View {
VStack {
Text("Postリクエストを送信しました")
.font(.title2)
// ここにロジックを実装
}
.padding()
// この画面にもタイトルを設定できます
.navigationTitle("Get")
}
}
// プレビュー用のコード (画面の確認用)
#Preview {
GetRequestView()
}
POSTリクエストのコード
import SwiftUI
struct PostRequestView: View {
var body: some View {
VStack {
Text("Postリクエストを送信しました")
.font(.title2)
// ここにロジックを実装
}
.padding()
// この画面にもタイトルを設定できます
.navigationTitle("Post")
}
}
// プレビュー用のコード (画面の確認用)
#Preview {
PostRequestView()
}
API側の実装
大きくは語りません
以下を参考にFast APIでレスポンスを返すようにしておきます
APIとの通信を実装
APIの準備も完了したので、ついにアプリとAPIの通信を実装してみます
iOS 15以降は、Swiftではasync/await構文を使用して非同期通信をより簡潔に記述することが推奨されていルトの忠告もありました
例としては以下のようなコード実装をするようです
func fetchDataAsync() async throws -> Data {
guard let url = URL(string: "リクエストするURL") else {
throw URLError(.badURL)
}
// try-awaitで、コールバックを使わずにデータとレスポンスを取得(ここでリクエストを送信)
let (data, response) = try await URLSession.shared.data(from: url)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw URLError(.badServerResponse)
}
return data
}
エラー処理はいろいろしなければいけないと思いますが、リクエストするURLにrenderで構築したAPIに向けたURL
を指定すればAPI通信ができるようになるといった手筈です
if let decodedString = String(data: data, encoding: .utf8) {
await MainActor.run {
self.message = "サーバーからの応答: \(decodedString)"
self.errorMessage = nil // 成功したのでエラーをクリア
}
} else {
await MainActor.run {
errorMessage = "応答データのデコードに失敗しました。"
message = "" // エラーなのでメッセージはクリア
}
}
今回は上記のようにしておいてGetリクエストで返却されたレスポンスデータを簡単に表示しています
Mac上でビルドしたあとのシミュレーターの画面になります
Postの方は同じようにやれるはずなので、説明はスキップします
終わりに
ということで以上が一通りアプリとAPIの通信を行う流れでした
慣れるまではこの一連の繰り返しを行って習慣づけていくしかないのかなと思うことばかりでした
挫けずに継続していきたいと思います