見出し画像

iOS基礎④

アニメーションをつける方法

アニメーションをつける方法はいくつかある
例えばListにアイテムを追加する処理の場合、
.transition(.opacity) を指定することで、アイテムが追加されたときにフェードインする効果が適用されます。
他にも、.transition(.scale) で拡大しながら現れる効果など、用途に応じていろいろな transition が利用可能です。
上記効果を発火させるのには、withAnimationを使う。
例えば、ボタンタップ時に発火させるならば、こんな感じ

Button(action: {
    withAnimation(.easeInOut) {
        //アイテム追加処理
    }
})
アプリ再起動してもデータが消えないようにする永続化手法

アプリ再起動してもデータが消えないようにする永続化手法

アプリ全体で同じ永続化ストア(ModelContainer)を使うため、アプリのエントリーポイントでModelContainerを作成する必要がある。
以下のような感じ

var sharedModelContainer: ModelContainer = {
        do {
            let schema = Schema([Task.self])
            let container = try ModelContainer(for: schema)
            return container
        } catch {
            fatalError("モデルコンテナの作成に失敗しました: \(error)")
        }
    }()

Viewに渡すには、
.modelContainer(sharedModelContainer) 修飾子を使って、作成した ModelContainer を ContentView の環境値として注入します。
以下のような感じ

        WindowGroup {
            ContentView()
                .modelContainer(sharedModelContainer) // ここで共有のコンテナを注入
        }

重要なポイントview側では、
@Environment(\.modelContext) を使い注入されたコンテナを取得することは出来るが、init 内では環境値(modelContext)はまだ使えない
@StateObject で TaskViewModel を管理している場合、仮の ModelContainer を作成してその mainContext を初期値として渡し、
その後、onAppearでModelContextを行う
例)initの処理

    init() {
        // 初期化時は、環境値はまだ利用できないため、仮の ModelContainer を作成しておく
        let schema = Schema([Task.self])
        let dummyContainer = try! ModelContainer(for: schema)
        _viewModel = StateObject(wrappedValue: TaskViewModel(modelContext: dummyContainer.mainContext))
    }

例)onAppearの処理

    .onAppear {
        // modelContext は App で設定した sharedModelContainer の mainContext になっているはず
        if viewModel.modelContext !== modelContext {
            viewModel.modelContext = modelContext  // ここで正しい ModelContext を設定
            viewModel.loadTasks()  // 再読み込みして永続化されたデータを取得
        }
    }

ちなみに、onAppearの発火タイミングは、
1.ビューが初めて表示されるとき、2.再表示される時、3.親ビューの更新により、子ビューが再生成されるとき
である。(3は条件があって、子ビューが画面上に残っていたら発火しないらしい)

いいなと思ったら応援しよう!