🐨

SwiftのCore DataとSwift Dataって何が違うのか整理

2025/01/15に公開

ネイティブ言語を再学習中...

iPhone上でのAIモデル(LLMやSLM、音声認識など)の推論が現実的になってきているので、Swiftを再学習中です。
React NativeとかFlutter用のパッケージが出るのはまだまだ先だろうなというのと、パフォーマンス面を考えたらネイティブ言語で作っちゃったほうが良いかなーと思い。

「Storage」というのがある

早速プロジェクトを用意してアプリ作りながら勉強しよーと思ったら、「Storage」たるものがありました。
普段かReact NativeかFlutterしか使わない自分からしたら見慣れないものでした。
Core DataSwift Dataの二つ選択できるようです。(もちろんNoneで選択しないもOK)

Core Dataとは

かなり昔、iOS開発初期あたりから存在するデータ永続化ライブラリです。
データモデルの定義はコードではなく、XcodeのGUI上で設定する必要があるとのこと。
(これが良くもあり悪くもあるらしいです...)

長く使われているためObjective-Cにも対応していたりSwift Dataに比べて出来ることは多い反面、Swift UIといった最近の書き方との連携が難しいようです。
学習コストも高いです。
保存先のデータベースはSQLiteが使用されています。

https://developer.apple.com/documentation/coredata

Swift Dataとは

最近新しく出たフレームワークのようでCore Dataよりシンプルに、学習コストもかなり低いそうです。
あとはCore Dataで課題だったSwift UIとの連携もシームレスにできて相性が良くなりました。
Core Dataとの大きな違いで、モデルの定義をコードで出来るようになりました。

注意としてiOS17以降のアプリじゃないと使用ができません。

https://developer.apple.com/jp/videos/play/wwdc2023/10189/

書き方

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) {
               ...
            }
        }
    }

}

実際に書いてみるとかなりシンプルになったなーと実感しました。

使い道

  1. API Keyやユーザーデータの保存
  2. サーバーからAPIで取得したデータのコピー・保存(APIリクエストの節約)
  3. ユーザー間でデータ連携が必要ないアプリを作るとき

結論

今から始めるなら圧倒的にSwift Dataが良いが、アプリの規模がデカかったりiOS17以前のバージョンも対応しないといけない場合はCore Dataを選んだ方が良さそう。
Swift DataはCore Dataの基盤を引き継いで作成されたライブラリなので、もし途中から移行となってもそんなに難しくはないようです。

ヘッドウォータース

Discussion