Apollo iOS チュートリアル (4)
詳細ビューを完成させます。
1. 詳細ビューの情報取得方法
詳細ビューの情報を取得する方法は、いくつかあります。
(1) LaunchListクエリで、全ての詳細ビューの情報を取得
(2) 別のクエリで、個別の詳細ビューの情報を取得
今回は、(2)の方法を使います。GraphQLの利点の1つは、ページに表示する必要のあるデータを正確に照会できることにあります。追加情報を表示しない場合は、必要になるまでデータを要求しないことで、帯域幅、実行時間、バッテリー寿命を節約できます。
2. GraphiQLでのクエリの確認
詳細ビューの情報を取得するクエリ「LaunchDetails」を作成します。
(1) 以下のクエリをGraphiQLで入力。
・(GraphiQL)
query LaunchDetails($id:ID!) {
launch(id: $id) {
id
site
mission {
name
missionPatch(size:LARGE)
}
rocket {
name
type
}
isBooked
}
}
「ID!」の「!」は、nullにできないの意味になります。
【注意】
GraphQL と Swift で null の扱いが 異なるので注意してください。Swiftでは、プロパティの型に「?」「!」の注釈を付けない場合、そのプロパティはnullにできません。GraphQLでは、フィールドの型に「!」を付けない場合、そのフィールドはnullにできます。
(2) GraphiQLの画面の左下の「QUERY VARIABLES」を選択して、以下を入力。
・(GraphiQL)
{ "id": "25" }
これは、クエリの実行時に$idに25を入力するという設定になります。
(3) 再生ボタンを押す。
「id 25」の情報が表示されます。
(3) LaunchDetails.graphql にクエリをコピーして、アプリをビルド。
3. 詳細ビューの編集
(1) DetailViewController.swift を以下のように編集。
・DetailViewController.swift
import UIKit
import Apollo
class DetailViewController: UIViewController {
// ランチID
var launchID: GraphQLID? {
didSet {
self.loadLaunchDetails()
}
}
// クエリ
private var launch: LaunchDetailsQuery.Data.Launch? {
didSet {
self.configureView()
}
}
// UI
@IBOutlet private var missionPatchImageView: UIImageView!
@IBOutlet private var missionNameLabel: UILabel!
@IBOutlet private var rocketNameLabel: UILabel!
@IBOutlet private var launchSiteLabel: UILabel!
@IBOutlet private var bookCancelButton: UIBarButtonItem!
// ビューの設定
func configureView() {
// launchの取得
guard
self.missionNameLabel != nil,
let launch = self.launch else {
return
}
// ミッション
self.missionNameLabel.text = launch.mission?.name
self.title = launch.mission?.name
// イメージ
let placeholder = UIImage(named: "placeholder")!
if let missionPatch = launch.mission?.missionPatch {
self.missionPatchImageView.sd_setImage(
with: URL(string: missionPatch)!, placeholderImage: placeholder)
} else {
self.missionPatchImageView.image = placeholder
}
// サイト
if let site = launch.site {
self.launchSiteLabel.text = "Launching from \(site)"
} else {
self.launchSiteLabel.text = nil
}
// ロケット名
if
let rocketName = launch.rocket?.name ,
let rocketType = launch.rocket?.type {
self.rocketNameLabel.text = "🚀 \(rocketName) (\(rocketType))"
} else {
self.rocketNameLabel.text = nil
}
// 予約
if launch.isBooked {
self.bookCancelButton.title = "Cancel trip"
self.bookCancelButton.tintColor = .red
} else {
self.bookCancelButton.title = "Book now!"
self.bookCancelButton.tintColor = self.view.tintColor
}
}
// ビューロード時に呼ばれる
override func viewDidLoad() {
super.viewDidLoad()
// UIをクリア
self.missionNameLabel.text = "Loading..."
self.launchSiteLabel.text = nil
self.rocketNameLabel.text = nil
self.configureView()
}
// ランチ詳細の読み込み
private func loadLaunchDetails() {
// ランチIDの取得
guard
let launchID = self.launchID,
launchID != self.launch?.id else {
return
}
// ランチ詳細の読み込み
Network.shared.apollo.fetch(query: LaunchDetailsQuery(id: launchID)) {
[weak self] result in
// selfの取得
guard let self = self else {
return
}
switch result {
// エラー時
case .failure(let error):
print("NETWORK ERROR: \(error)")
// 成功時
case .success(let graphQLResult):
if let launch = graphQLResult.data?.launch {
self.launch = launch
}
if let errors = graphQLResult.errors {
print("GRAPHQL ERRORS: \(errors)")
}
}
}
}
}
4. ストーリーボードの編集
◎ StackViewの追加
(1) 「Detail Scene → Detail → View」に「(Horizontal) StackView」を追加。
(2) 制約を、次のように指定。
(3) 属性を、次のように指定。
◎ ImageViewの追加
(1) 「StackView」に「UIImageView」を追加し、名前に「Mission Patch Image View」を指定。
(2) 「View」と「UIView」を両方選択し、以下の制約を追加。
(3) 追加した制約を選択し、次のように更新。
画面のサイズに関係なく、画像の幅が常に画面の40%になる制約になります。
(4) 「Mission Patch Image View」を選択し、以下の制約を追加。
(5) 追加した制約を選択し、次のように更新。
幅と高さが常に等しくなる制約になります。
(6) 「Mission Patch Image View」を「missionPatchImageView」アウトレットに接続。
◎ 2番目のStackViewの追加
(1) 2番目の「(Vertical) StackView」を1番目の「StackView」に追加。
(2) 属性を、次のように指定。
◎ Labelの追加
(1) 2番目の「StackView」に「Label」を追加し、以下の属性を指定。
(2) 「Label」を「missionNameLabel」アウトレットに接続。
◎ 2番目のLabelの追加
(1) 2番目の「StackView」に2番目の「Label」を追加し、以下の属性を指定。
(2) 2番目の「Label」を「rockageNameLabel」アウトレットに接続。
◎ 3番目のLabelの追加
(1) 2番目の「StackView」に3番目の「Label」を追加し、以下の属性を指定。
(2) 3番目の「Label」を「launchSiteLabel」アウトレットに接続。
◎ BarButtonItemの追加
(1) 「BarButtonItem」をナビゲーションバーの右上にドラッグし、以下の属性を指定。
(2) 「BarButtonItem」を「bookCancelButton」アウトレットに接続。
◎ 完成
3. 実行
ビルドしてアプリを実行すると、次のようにランチ情報が表示されます。
この記事が気に入ったらサポートをしてみませんか?