SwiftUI入門-勉強メモ017-【Core Dataその1】

Core Dataはデータベースを利用できるようにするフレームワークです. Core Dataを用いることによって, データの永続化が可能になり, アプリにはなくてはならないものです.

Use Core Data to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device.

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

Pythonでコードを書いていた頃は, SQLを直接いじってました. SwiftUIではその環境もちゃんと用意してくれています. SQLは慣れるまで大変なので, 嬉しいですね.

環境は,

  • macOS Catalina 10.15.7
  • Xcode 12.0.1
  • Swift 5.3
  • iOS 14.0

です.

ここでは, メモを保存するアプリを作成していきます. アプリを落としたあともデータは保存されます.

目次

Core Dataを含んだプロジェクトを作成しよう

Create a new Xcode project」から新しいプロジェクトを作成します.

SwiftUI

iOS」「App」を選択し, 「Next」を選択します.

Choose a template for your new project」画面で,

  • Interface→SwiftUI
  • Life Cycle→UIKit App Delegate
  • Language→Swift
  • Use Core Dataにチェック

とします.

SwiftUI

これで準備は完了です. あとから既存のプロジェクトにCore Dataを入れることもできます. ただ, 少し大変なので今回は最初からCore Dataを組み込んだプロジェクトを作成しました.

これにより,

  • Core DataのEntityを定義するファイル「SimpleMemo.xcdatamodeld」の⽣成
  • Core Dataに対応した「AppDelegate.swift」「SceneDelegate.swift」の⽣成

されました.

SwiftUI

Core Dataの世界の「Entity」は,

  • Swiftの世界では「Class」
  • Databaseの世界では「テーブル」

のイメージです.

impleCoreData.xcdatamodeldで登録したいEntityに含まれるAttributeを設定します. Attributeは, Swiftの世界では「Classのプロパティ」に相当します.

「Entityに含まれるAttribute」とは, 具体例で言えば, 氏名, 年齢, 生年月日などの各情報のことです. ここで登録したい情報をまとめます.

そもそもAppDelegate.swiftとSceneDelegate.swiftには何が追加されたのか?

AppDelegate.swift内の追加について

SwiftUI

上の❶, ❷が追加されています.

コメントが多くて追加された内容が多く見えますが, コメントをとってしまえば次のようになります.

SwiftUI

データを操作するオブジェクトの生成とデータを保存するための関数の作成をしています.

SceneDelegate.swift内の追加について

2ヶ所追加されています.

SwiftUI

scene関数内では, NSManagedObjectContextオブジェクトへのアクセスをEnvironmentObjectに設定しています. これにより, View内でのデータの受け渡しが可能となり, Core Dataへのデータ保存が行えます.

SwiftUI

sceneDidEnterBackground内でsaveContextを呼び出しています. これでアプリがバックグラウンドに入ったとき, データベースの保存処理が行われます.

Core Dataで出てくる用語を自分なりに解釈し直してみました

Core Data自分なりの解釈RDB的には?Apple Developerの説明
NSManagedObjectModelDBを書き込むプログラムを記述したもの.
Xcode上では.xcdatamodeldファイル
クエリのルールを決めたもの?A programmatic representation of the .xcdatamodeld file describing your objects.
NSManagedObjectContextアプリのデータの変更を操作したり, 追跡したりする.クエリ.
データベースに対する命令文.
An object space that you use to manipulate and track changes to managed objects.
NSPersistentStoreCoordinatorこれを利用することによって, contextとDBがやり取りできるようになっている.クエリをDBに伝える.A coordinator that uses the model to help contexts and persistent stores communicate.
NSPersistentContainer上の3つ
NSManagedObjectModel, NSPersistentStoreCoordinator, NSManagedObjectContext
をまとめている.
クエリとそのルールや伝達方法をまとめて管理する.A container that encapsulates the Core Data stack in your app.
NSManagedObjectCore Dataを扱うための動作を実装する.レコード.
横一列のデータのこと.
A base class that implements the behavior required of a Core Data model object.
NSFetchRequestデータを取得するための検索条件の説明A description of search criteria used to retrieve data from a persistent store.
NSFetchRequestResult検索したデータ結果の保持An abstract protocol used with parameterized fetch requests.
この表はまだ未完成です. 随時, 追加編集を加えていきます.
Pierrot

ちなみに, NSObjectのNSは, NeXTSTEPの略です. 歴史を感じます.

EntityにAttributeを追加しよう

どんな情報を登録するのか, その定義をここではしていきます.

impleCoreData.xcdatamodeldで「Add Entity」から新しいEntityを作成します. Entityの名前は「Memo」とします.

SwiftUI

Entityが作成できたら, Attributeを追加していきます. 「+」ボタンから追加することができます.

SwiftUI
SwiftUI

ここでは

text→String型, id→UUID型

とします.

SwiftUI

データタイプはさまざまな型が用意されています.

Type説明
integer 16-32768〜32767の整数
(-3万〜3万)
integer 32-2147483648〜2147483647の整数
(-21億〜21億)
integer 64-9223372036854775808〜9223372036854775807の整数
(-922京〜922京)
Decimal10進型
仮数は10進数の38桁整, 指数は-128〜127の整数
四則演算を行うためのもの
Double64ビット不動小数点
有効桁数は約15桁
Float32ビット不動小数点
有効桁数は約7桁
String文字列
Blooean真理値(trueとfalse)
Date日付
Binary Dataバイナリデータ
UUIDUUID(Universally Unique Identifier)
128ビットの識別子
URIURI(Uniform Resource Identifier)
Web上のファイルを認識するための識別子
TransformableNSObject型に変換できる
Undefined未設定

一応, ここで一回ビルドしておきます.

ContentView.swiftのコードを書こう

コードを書いていきます. 全体のコードは次のようになります.

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) var context
    @FetchRequest(
        entity: Memo.entity(),
        sortDescriptors: []
    )
    var memos: FetchedResults<Memo>
    @State private var memoName: String = ""
    var body: some View {
        VStack {
            HStack{
                TextField(
                    "追加するメモ",
                    text: $memoName
                )
                .border(Color.blue, width: 2)
                Button(action: {
                    let newMemo = Memo(context: context)
                    newMemo.id = UUID()
                    newMemo.text = memoName
                    try! context.save()
                }){
                    Text("追加")
                }
            }.padding(.all)
            List {
                ForEach(memos){ memo in
                    Text(memo.text!)
                }
            }
        }
    }
}

コードは以下のようになっています.

SwiftUI
データベースの操作にはNSManagedObjectContextのインスタンスが必要になります.
それをここで取得しています.
データを取得するための検索条件の設定をここで行います.
今回は特に条件を指定していません.
検索したデータ結果の保管場所をここで用意します.
追加するテキストを入れる変数をここで用意します.
追加するテキスト入力をここで行います.
ボタンを押すと, データが保存されます.
データを取得する度にリストでデータを表示しなおします.

Cannot find type ‘Memo’ in scopeと出たら…

コードを書き終わったとき,

Cannot find type ‘Memo’ in scope

というエラーが出ることがあります.

Memoを設定し終わった後, 一度コンパイルする必要があるんですかね?

SwiftUI

この場合,

command+shift(↑)+Kでキャッシュをクリアし, Xcodeを一旦完全に終了させてからプロジェクトを開き直す

と解決します.

さまざまな問題は蓄積

簡単なメモアプリは作成できましたが, 問題もたくさんあります.

  • リストが入力したデータ順に並ばない.
  • 追加したメモを削除することができない.
  • メモは「追加」ボタンを押さないと追加されない.
    例えば, テキストフィールドで入力が完了したときに自動的に追加されてもよい.

例えば, メモにアルファベットを順番に入れていくと,

SwiftUI

のように, 順番に表示されることはありません.

次回はこれらを修正していきます.

よかったらシェアしてね!

コメント

コメントする

目次
閉じる