編集画面をつくる
チュートリアルより
まずプロフィールのデータ構造は
struct Profile { var username: String var prefersNotifications: Bool var seasonalPhoto: Season var goalDate: Date // デフォルト設定 static let `default` = Self(username: "g_kumar", prefersNotifications: true, seasonalPhoto: .winter) init(username: String, prefersNotifications: Bool = true, seasonalPhoto: Season = .winter) { self.username = username self.prefersNotifications = prefersNotifications self.seasonalPhoto = seasonalPhoto self.goalDate = Date() } // enumにCaseIterableつけとく enum Season: String, CaseIterable { case spring = "🌷" case summer = "🌞" case autumn = "🍂" case winter = "☃️" } }
編集画面にある日付Pickerの日付指定の範囲の作成が面白い
var dateRange:ClosedRange<Date> { let min = Calendar.current.date(byAdding: .year, value: -1, to: profile.goalDate)! let max = Calendar.current.date(byAdding: .year, value: 1, to: profile.goalDate)! return min...max }
編集画面は
import SwiftUI struct ProfileEditor: View { // 双方向バインディング @Binding var profile:Profile var dateRange:ClosedRange<Date> { let min = Calendar.current.date(byAdding: .year, value: -1, to: profile.goalDate)! let max = Calendar.current.date(byAdding: .year, value: 1, to: profile.goalDate)! return min...max } var body: some View { List { HStack { Text("UserName").bold() Divider() // ユーザープロファイル TextField("Username", text: $profile.username) } Toggle(isOn:$profile.prefersNotifications) {Text("Enable Notifications")} VStack(alignment: .leading, spacing: 20) { Text("Seasonal Photo").bold() // ピッカー、季節を選ぶ。セグメント Picker("Seasonal Photo", selection: $profile.seasonalPhoto) { ForEach(Profile.Season.allCases, id: \.self) { season in Text(season.rawValue ).tag(season)} }.pickerStyle(SegmentedPickerStyle()) } .padding(.top) // 日付ピッカー VStack(alignment: .leading, spacing: 20) { Text("Goal Date").bold() DatePicker( "Goal Date", selection: $profile.goalDate, in: dateRange, displayedComponents: .date ) } .padding(.top) } } } struct ProfileEditor_Previews: PreviewProvider { static var previews: some View { ProfileEditor(profile: .constant(.default)) } }
プロフィール画面の全体は
import SwiftUI struct ProfileHost: View { /// editModeはEnvironmentValuesでもともとある環境変数で、エディットモードであるかないか @Environment(\.editMode) var mode /// 環境変数、.environmentObject(UserData())で渡される。 @EnvironmentObject var userData: UserData @State var draftProfile = Profile.default var body: some View { VStack(alignment: .leading, spacing: 20) { HStack { /// キャンセルボタンは編集モードのときのみ出る if self.mode?.wrappedValue == .active { Button("Cancel") { /// キャンセルするとドラフトはユーザープロフィールに戻る self.draftProfile = self.userData.profile self.mode?.animation().wrappedValue = .inactive } } Spacer() EditButton() } /// 編集画面かそうでないかの出し分けをする if self.mode?.wrappedValue == .inactive { ProfileSummary(profile: draftProfile)// 表示はドラフトを使う } else { ProfileEditor(profile: $draftProfile)// 表示はドラフトを使う .onAppear { /// 編集画面が表示されるとき、ユーザープロフィールをドラフトにする self.draftProfile = self.userData.profile } .onDisappear { /// 編集画面が消える時にドラフトをユーザーのプロフィールにする self.userData.profile = self.draftProfile } } } .padding() } } struct ProfileHost_Previews: PreviewProvider { static var previews: some View { ProfileHost().environmentObject(UserData()) } }