SwiftData

2023 年 9 月 18 日

對 SwiftUI Scene 設定 SwiftData 的 modelContext

已複製到剪貼板


使用 modelContext 可以設定 SwiftUI Scene 中的 environment 變數「modelContext」。

SwiftData logo

modelContext 概覽

比起 modelContainer 來說,使用 modelContext 來設定 SwiftUI Scene 的 model context,相對複雜許多,網路上也幾乎沒有範例。

@main
struct Example: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContext(ModelContext)
    }
}

使用 modelContext Scene Modifier 必須 create 一個 ModelContext 給它。

Init 一個 ModelContext

要 create 一個 ModelContext 可以直接在後面加括號:

.modelContext(ModelContext(container: ModelContainer))

或更直接的使用 .init:

.modelContext(.init(container: ModelContainer))

可以看到裡面是吃一個 ModelContainer,所以我們要 create 一個 ModelContainer 給它。

Init 一個 ModelContainer

要 create 一個 ModelContainer 就沒那麼容易,因為 ModelContainer 的 init 會 throws,所以我們必須要用 try catch 去包它。通常我們可以把 ModelContainer 的 init 移到 ViewModel 裡去做,在 init 裡只需拿 ViewModel 的變數。

但這裡為了方便說明,就直接使用 try!

.modelContext(.init(
    try! .init(
        for: PersistentModel.Type..., 
        configurations: ModelConfiguration...
    )
))

第一個參數:PersistentModel.Type...

這裡要提供我們想儲存的 Swift class 給 SwiftData 管理。假設我們想儲存的 Swift class 叫做 DataModel,可以這樣寫:

SwiftData.Schema([DataModel.self])

Array 裡可以放多個我們想儲存的 Swift class。

第二個參數:ModelConfiguration...

這裡可以對我們的 SwiftData Model 做設定。我們就直接使用最簡單的 .init:

[.init(isStoredInMemoryOnly: false)]

這裡的 isStoredInMemoryOnly 指的是要不要只儲存在記憶體裡就好,預設是 true,App 關掉後資料就會被清掉,但給 false 的話,就不會只存在記憶體裡,App 關掉再重開資料也還會在,這通常才是我們想要的,畢竟使用 SwiftData 就是要存永久的資料。

所以最終我們的 code 會長這樣:

.modelContext(.init(
    try! .init(
        for: SwiftData.Schema([DataModel.self]), 
        configurations: [.init(isStoredInMemoryOnly: false)]
    )
))

使用 SwiftData 存的資料

上面我們對 Scene 設定了 modelContext,就代表裡面的 View 可以存取 Environment 中的 modelContext 與 SwiftData 管理的 Model 了。

抓 SwiftData 中的資料

如果只是要顯示 SwiftData 中存得資料的話,可以使用 @Query:

@Query private var dataModel: [DataModel]

型別給我們在 SwiftData.Schema 中有寫到的型別,@Query 就能抓到存在 SwiftData 中的資料。

處理 SwiftData 中的資料

而如果要處理資料,像是:插入(insert)、刪除(delete)、儲存(save)⋯⋯ 的話,可以用 @Environment 拿環境中的 modelContext,再用 modelContext.insert(_ model:) 或 modelContext.delete(_ model:) 之類的。

@Environment(\.modelContext) private var modelContext

分享文章

已複製到剪貼板

主題文章

查看 SwiftData

超級感謝

關於 XcodeProject

XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。


Contacts

Ricky Chuang

XcodeProject

RickyChuang.xcodeproj@gmail.com

XcodeProject 聯絡

contact.xcodeproj@gmail.com

最新文章