はじめに
前回からの続きでSwiftUIのチュートリアル入門で、[Handling User Input編]になります。
もと記事サイト
Step0
このセクションではLandmark
の詳細画面にお気に入りボタンを設置し、お気に入りの登録・解除の変更を@Binding
を使用してModelData
に反映するようにします。
Step1
最初にお気に入りボタンとなるFavoriteButton.swift.
を作成します。
import SwiftUI
struct FavoriteButton: View {
var body: some View {
Text("Hello, World!")
}
}
struct FavoriteButton_Previews: PreviewProvider {
static var previews: some View {
FavoriteButton()
}
}
Step2
isSet
プロパティを宣言します。その際に@Binding
を付与します。これでisSet
の変更内容がModelData
のisFavorite
に反映されるようにします。
またFavoriteButton_Previews
にもイニシャライザでisSet
を渡します。@Binding
を付与しているためisSet
の型が@Binding<Bool>
となっているので、.constant(true)
で変換します。
import SwiftUI
struct FavoriteButton: View {
@Binding var isSet: Bool
var body: some View {
Text("Hello, World!")
}
}
struct FavoriteButton_Previews: PreviewProvider {
static var previews: some View {
FavoriteButton(isSet: .constant(true))
}
}
Step3
ボタンを設置します。ボタンを押された際にisSet
の値を反転します。
お気に入りボタンらしくなるように星の画像も追加します。
import SwiftUI
struct FavoriteButton: View {
@Binding var isSet: Bool
var body: some View {
Button(action: {
isSet.toggle()
}) {
Image(systemName: isSet ? "star.fill" : "star")
.foregroundColor(isSet ? Color.yellow : Color.gray)
}
}
}
struct FavoriteButton_Previews: PreviewProvider {
static var previews: some View {
FavoriteButton(isSet: .constant(true))
}
}
Step4
ファイルが増えてきたのでフォルダーを作成して整理します。CircleImage.swift
、 MapView.swift
、FavoriteButton.swift
をHelpers
フォルダーを作成して中にいれます。Landmarks
フォルダーを作成しLandmarkList.swift
、LandmarkRow.swift
、LandmarkDetail.swift
を中にいれます。
Step5
LandmarkDetail.swift
を選択し、対象のLandmarkがModelDataのlandmarks配列の何番目に保存されているのか比較できるように、@EnvironmentObject
でmodelData
を親Viewから受け取れるようにします。LandmarkDetail_Previews
にも変更を加えます。
比較する際にlandmarkIndex
を使用してid
が一致する要素番号を取得しています。
import SwiftUI
struct LandmarkDetail: View {
@EnvironmentObject var modelData: ModelData
var landmark: Landmark
var landmarkIndex: Int {
modelData.landmarks.firstIndex(where: { $0.id == landmark.id })!
}
var body: some View {
ScrollView {
MapView(coordinate: landmark.locationCoordinate)
.ignoresSafeArea(edges: .top)
.frame(height: 300)
CircleImage(image: landmark.image)
.offset(y: -60)
.padding(.bottom, -60)
VStack(alignment: .leading) {
Text(landmark.name)
.font(.title)
HStack {
Text(landmark.park)
.font(.subheadline)
Spacer()
Text(landmark.state)
.font(.subheadline)
}
.font(.subheadline)
.foregroundColor(.secondary)
Divider()
Text("About \(landmark.name)")
.font(.title2)
Text(landmark.description)
}
.padding()
}
.navigationTitle(landmark.name)
.navigationBarTitleDisplayMode(.inline)
}
}
struct LandmarkDetail_Previews: PreviewProvider {
static let modelData = ModelData()
static var previews: some View {
LandmarkDetail(landmark: modelData.landmarks[0])
.environmentObject(modelData)
}
}
Step6
landmarkの名前を表示しているText
をHStack
で囲み、FavoriteButton
を追加します。
その際のイニシャライザにisSet
にmodelData.landmarks[landmarkIndex].isFavorite
を渡しますが、先頭に$を付与することでisSet
とmodelData.landmarks[landmarkIndex].isFavorite
をバインドさせてmodeldata
のlandmark.isFavorite
を自動で更新させています。
import SwiftUI
struct LandmarkDetail: View {
@EnvironmentObject var modelData: ModelData
var landmark: Landmark
var landmarkIndex: Int {
modelData.landmarks.firstIndex(where: { $0.id == landmark.id })!
}
var body: some View {
ScrollView {
MapView(coordinate: landmark.locationCoordinate)
.ignoresSafeArea(edges: .top)
.frame(height: 300)
CircleImage(image: landmark.image)
.offset(y: -60)
.padding(.bottom, -60)
VStack(alignment: .leading) {
HStack {
Text(landmark.name)
.font(.title)
FavoriteButton(isSet: $modelData.landmarks[landmarkIndex].isFavorite)
}
HStack {
Text(landmark.park)
.font(.subheadline)
Spacer()
Text(landmark.state)
.font(.subheadline)
}
.font(.subheadline)
.foregroundColor(.secondary)
Divider()
Text("About \(landmark.name)")
.font(.title2)
Text(landmark.description)
}
.padding()
}
.navigationTitle(landmark.name)
.navigationBarTitleDisplayMode(.inline)
}
}
struct LandmarkDetail_Previews: PreviewProvider {
static let modelData = ModelData()
static var previews: some View {
LandmarkDetail(landmark: modelData.landmarks[0])
.environmentObject(modelData)
}
}
Step7
LandmarkList.swift
を選択し、ライブプレビューを実行してみましょう。
詳細画面で変更したお気に入りボタンのステータスが一覧画面に戻ると反映されていることが確認できます。
Landmarkの名前の隣にあるお気に入りの星をタップします。
一覧画面に戻ると先程の変更が反映されています!
まとめ
今回でHandling User Input編もお終いになります。ユーザのアクションを@Binding
を使用してデータソースと同期する方法がわかりました。これで簡単なアプリなら作成できそうですね。
次回からは[Drawing Paths and Shapes]編になります。図形の描画はレイアウト組む際に必要になることもあるので頑張って勉強しましょう。
コメント