Home 寫程式從零開始學SwiftData

從零開始學SwiftData

by 艾普利

Photo by Nathan da Silva on Unsplash

WWDC23 中發表了一個新的Framework – SwiftData,它是本機端資料儲存方式之一,過去若想用DB方式將資料存在本機端最常用的就二種,一是iOS本家的Core Data,另一個就是第三方工具的SQLite,Core Data 雖然很好用,但是前置作業非常麻煩,設定完之後一定不會記得,所以SQLite看起來比較多人喜歡。

然而SwiftData 簡化了非常多Core Data 需要做的事情,讓資料儲存變得非常簡單,當然也完全支援SwiftUI,這樣的東西怎麼可以不學起來呢?

本篇主要會使用Apple 與 AppCoda 的教學來學習


想要使用SwiftData 需要使用 Xcode15 & iOS 17 才行

本篇的參考教學文章在此

Apple

AppCoda

本文章的程式碼多數來自於Apple的 Sample code


SwiftData 是和Core Data 一樣可以讓你將資料儲存在本機端中,它特別的地方在於可以直接將寫好的DataModel 變成是儲存的物件且寫法非常簡單,首先需要寫好一個DataModel,請注意必需要使用Class 才行

建立Model

若是下載原本的Sample code 的話配合WWDC23的影片一起學習會比較好喔,我是直接抓重點來說,借用在 Building a document-based app using SwiftData 的範例中的 Card DataModel

final class Card {
    var front: String
    var back: String
    var creationDate: Date

    init(front: String, back: String, creationDate: Date = .now) {
        self.front = front
        self.back = back
        self.creationDate = creationDate
    }
}

若要把這個Card 變成 SwiftData 的 Model的話,只要做二個步驟

第一是 import SwiftData

第二是在 Class 加上 @Model

好,完工

import SwiftData

@Model
final class Card {
    var front: String
    var back: String
    var creationDate: Date

    init(front: String, back: String, creationDate: Date = .now) {
        self.front = front
        self.back = back
        self.creationDate = creationDate
    }
}

沒錯,就是這麼簡單! 如果想要設定 Unique Key 例如像是 ID 之類的,當然可以設定,只要在參數前面加上 @Attribute(.unique) 就行了

@Model
final class Card {
    @Attribute(.unique) var cardId: String
    ...
}

還有一個比較特別的寫法是,如果哪天想要為這個參數變更名字,又不想要讓這個參數變成是一個新的參數,可以使用 @Attribute(originalName:),這樣它就會自動對應到過去的名稱

@Model
final class Card {
    @Attribute(originalName: "creationDate") var creation_Date: Date
    ...
}

在SwiftUI 上使用

接著說明怎麼串接到 SwiftUI 的畫面裡,先找到有 @main 的檔案,在 ContentView() 下加上

.modelContainer(for: Card.self),modelContainer 記得先前在使用Core Data 的時候也有類似的設定,這裡是把想要做為SwiftData 的model 在 for: 後面,當然可以寫很多個用Array 形式來寫

import SwiftUI
import SwiftData

@main
struct SwiftDataFlashCardSample: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(for: Card.self)
        }
    }
}

接著在需要使用SwiftData 的View 上宣告 modelContext ,這就是用來做新增與刪除,再來就是要做Query ,只要宣告要使用的參數,這裡是 var cards: [Card],在最前面的地方寫上 @Query 就完成了,

import SwiftData
struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var cards: [Card]
    ...
}

也可以在Query 的時候加上 Sort 或 Filter

@Query(sort: \.creationData) private var cards: [Card]
@Query(filter: #Predicate<Person> { Person in $0.name == "John" }) private var persons: [Person]

加上 @Query 的參數就會自動追蹤變化,在參數有變更的時候自動更新畫面,所以並不需要特別做什麼處理。


資料操作

接著來說操作,資料操作主要的就是三個動作,新增(insert)、修改(update)與刪除(Delete)

Insert

Insert 的時候要使用到先前宣告過的 modelContext,呼叫 insert 的 function 即可

let newCard = Card(front: "Sample Front", back: "Sample Back")
modelContext.insert(newCard)

Update

其實寫上 @Model 的 Data Object,SwiftData 就會自動追蹤參數變化,只要是已經有新增過的 Item 不需要特別寫些什麼,SwiftData 就會自動去更新它的參數內容

Delete

Delete 的時候和 Insert 一樣,可以告訴它想刪除的item 是那一個,也可以寫條件刪除

let card = Cards[0]
modelContext.delete(card)

目前感覺SwiftData 比起Core Data 來說簡單很多,不過畢竟 SwiftData 才剛推出,功能就沒有 Core Data強大,就如同SwiftUI 剛推出的時候一樣,有很多UIKit 很容易做到的事情,SwiftUI 還沒有支援,相信之後SwiftData 功能會慢慢變多,就等它未來發展啦

最後祝大家 Coding 愉快!!

可以在這裡下載我依照 AppCoda 教學做出的Sample code

You may also like