Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

編集画面をつくる

チュートリアルより

まずプロフィールのデータ構造は

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())
    }
}