SwiftのCore DataとSwift Dataって何が違うのか整理
ネイティブ言語を再学習中...
iPhone上でのAIモデル(LLMやSLM、音声認識など)の推論が現実的になってきているので、Swiftを再学習中です。
React NativeとかFlutter用のパッケージが出るのはまだまだ先だろうなというのと、パフォーマンス面を考えたらネイティブ言語で作っちゃったほうが良いかなーと思い。
「Storage」というのがある
早速プロジェクトを用意してアプリ作りながら勉強しよーと思ったら、「Storage」たるものがありました。
普段かReact NativeかFlutterしか使わない自分からしたら見慣れないものでした。
Core DataとSwift Dataの二つ選択できるようです。(もちろんNoneで選択しないもOK)
Core Dataとは
かなり昔、iOS開発初期あたりから存在するデータ永続化ライブラリです。
データモデルの定義はコードではなく、XcodeのGUI上で設定する必要があるとのこと。
(これが良くもあり悪くもあるらしいです...)
長く使われているためObjective-Cにも対応していたりSwift Dataに比べて出来ることは多い反面、Swift UIといった最近の書き方との連携が難しいようです。
学習コストも高いです。
保存先のデータベースはSQLiteが使用されています。
Swift Dataとは
最近新しく出たフレームワークのようでCore Dataよりシンプルに、学習コストもかなり低いそうです。
あとはCore Dataで課題だったSwift UIとの連携もシームレスにできて相性が良くなりました。
Core Dataとの大きな違いで、モデルの定義をコードで出来るようになりました。
注意としてiOS17以降のアプリじゃないと使用ができません。
書き方
1. CoreData
GUIでのポチポチ操作とコードの繋ぎ込みで行います。
ファイル作成時に、CoreDataセクション内の「DataModel」を選択。
スクショのような感じでモデルの定義ができます。
ぶっちゃけコードで書いた方が速いと思います。
次にアプリ内で使用するためにPersistentContainerクラスを定義します。
class CoreDataStack: ObservableObject {
static let shared = CoreDataStack()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { _, error in
if let error {
fatalError("Failed to load persistent stores: \(error.localizedDescription)")
}
}
return container
}()
private init() { }
}
作成したPersistentContainerクラスをアプリに紐付けます。
@main
struct SampleApp: App {
@StateObject private var coreDataStack = CoreDataStack.shared
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext,
coreDataStack.persistentContainer.viewContext)
}
}
}
コード内で値を利用するときはEnvironment
を使用して呼び出します。
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
var body: some View {
}
}
データをコードで使用するまで結構色々やる必要あるなーという印象
2. SwiftData
モデルは通常のSwiftファイルで定義ができます。
書き方はPythonとかと似てますね。
ユニークキーは@Attribute(.unique)
を使用します。
import Foundation
import SwiftData
@Model
final class Player {
@Attribute(.unique) var id: UUID
var name: String
var score: Int
init(name: String, score: Int) {
self.id = UUID()
self.name = name
self.score = score
}
}
モデルをアプリに紐付けます。
import SwiftUI
import SwiftData
@main
struct SampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: [
Player.self
])
}
}
}
データの保存や更新する場合は@Environment
、アプリ内での表示や動的に追加する場合は@Query
を使用します。
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var context
@Query private var players: [Player]
var body: some View {
List {
ForEach(players) {
...
}
}
}
}
実際に書いてみるとかなりシンプルになったなーと実感しました。
使い道
- API Keyやユーザーデータの保存
- サーバーからAPIで取得したデータのコピー・保存(APIリクエストの節約)
- ユーザー間でデータ連携が必要ないアプリを作るとき
結論
今から始めるなら圧倒的にSwift Dataが良いが、アプリの規模がデカかったりiOS17以前のバージョンも対応しないといけない場合はCore Dataを選んだ方が良さそう。
Swift DataはCore Dataの基盤を引き継いで作成されたライブラリなので、もし途中から移行となってもそんなに難しくはないようです。
Discussion