
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は条件があって、子ビューが画面上に残っていたら発火しないらしい)