セクション 2
編集モードの追加
ユーザは、プロファイルの詳細の表示と編集を切り替える必要があります。EditButton を既存の ProfileHost に追加し、個々の値を編集するためのコントロールを備えたビューを作成することにより、編集モードを追加します。
ステップ 1
ProfileHost を選択し、モデルデータを環境オブジェクトとしてプレビューに追加します。
このビューは @EnvironmentObject 属性を持つプロパティを使用しませんが、このビューの子である ProfileSummary は使用します。したがって、修飾子がないと、プレビューは失敗します。
ステップ 2
環境の \.editMode をキーオフする Environment ビュープロパティを追加します。
SwiftUI は、@Environment プロパティラッパーを使用してアクセスできる環境の値の保管場所を提供します。editMode 値にアクセスして、編集のスコープの読み取りまたは書き込みを行います。
ステップ 3
環境の editMode 値のオンとオフを切り替える [Edit(編集)] ボタンを作成します。
EditButton は、以前の手順でアクセスしたものと同じ editMode 環境値を制御します。
ステップ 4
ModelData クラスを更新して、ユーザがプロファイルビューを閉じた後も存続するユーザプロファイルのインスタンスを含めます。
ステップ 5
環境からユーザプロファイルデータを読み取り、データの制御をプロファイルホストに渡します。
ユーザが名前を入力しているときなど、編集を確認する前にグローバルアプリの状態が更新されないようにするために、編集ビューはそれ自体のコピーを操作します。
ステップ 6
静的プロファイルまたは編集モードのビューのいずれかを表示する条件付きビューを追加します。
ライブプレビューを実行して編集ボタンをタップすると、[Edit(編集)] モードに入ったときの効果を確認できます。今のところ、Edit モードビューは単なる静的テキストフィールドです。
    ProfileHost.swift
- import SwiftUI
- struct ProfileHost: View {
@State private var draftProfile = Profile.default
var body: some View {
VStack(alignment: .leading, spacing: 20) {
ProfileSummary(profile: draftProfile)
}
.padding()
}
- }
- struct ProfileHost_Previews: PreviewProvider {
static var previews: some View {
ProfileHost()
.environmentObject(ModelData())
}
- }
プレビュー その 1
    ProfileHost.swift
- import SwiftUI
- struct ProfileHost: View {
@Environment(\.editMode) var editMode
@State private var draftProfile = Profile.default
var body: some View {
    ProfileHost.swift
var body: some View {
VStack(alignment: .leading, spacing: 20) {
HStack {
Spacer()
EditButton()
}
ProfileSummary(profile: draftProfile)
}
プレビュー その 2
    ModelData.swift
- import Foundation
- import Combine
- final class ModelData: ObservableObject {
@Published var landmarks: [Landmark] = load("landmarkData.json")
var hikes: [Hike] = load("hikeData.json")
@Published var profile = Profile.default
var features: [Landmark] {
landmarks.filter { $0.isFeatured }
}
var categories: [String: [Landmark]] {
Dictionary(
grouping: landmarks,
by: { $0.category.rawValue }
)
}
- }
- func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
- }
    ProfileHost.swift
- import SwiftUI
- struct ProfileHost: View {
@Environment(\.editMode) var editMode
@EnvironmentObject var modelData: ModelData
@State private var draftProfile = Profile.default
var body: some View {
VStack(alignment: .leading, spacing: 20) {
HStack {
Spacer()
EditButton()
}
ProfileSummary(profile: modelData.profile)
}
.padding()
}
- }
- struct ProfileHost_Previews: PreviewProvider {
static var previews: some View {
ProfileHost()
.environmentObject(ModelData())
}
- }
プレビュー その 3
    ProfileHost.swift
EditButton()
}
if editMode?.wrappedValue == .inactive {
ProfileSummary(profile: modelData.profile)
} else {
Text("Profile Editor")
}
}
.padding()
}