LoginSignup
8
9

More than 1 year has passed since last update.

【Swift】CoreDataで関係データベース

Last updated at Posted at 2022-05-13

はじめに

CoreDataでリレーションシップの機能を使ったので備忘録として残します。
前半は関係データベースについて、後半はCoreDataでの関係データベース設定方法について記述します。

環境

  • Swift: version 5.6
  • Xcode: Version 13.3.1 (13E500a)
  • macOS: 12.3.1 (21E258)

リレーションシップ(Relationship)とは?

エンティティ(Entity)同士の関係性。
リレーションシップの設定を行うことで関係データベースを構築することができる。

関係データベース

データを表で管理するデータベースのこと。
行(レコード)と列(属性)で構成される。

  • データのが追加されると行が増える。
  • 行には名前がないが、列には名前(属性名)がある

主キー

表の中からある特定の行を識別するための列。

主キーの条件

  1. データの重複がないこと。
  2. データが空でないこと。

複合主キー

複数の列を組み合わせてつくる主キーのこと。
上記の主キーの条件を満たす列がない場合に使用する。

外部キー

別の表の主キーを参照する列のこと。

正規化

データが重複したり、データの更新の際に矛盾が生じたりしないように表をわけること。

関係データベースを構築する

今回もポケモンを使って考えてみます。
ボックスと預けているポケモンの関係性が使えそうです。
こんなイメージ。
2022-05-13-00.png

1. Entityの作成

BoxPokemonの2つのエンティティを作成します。
2022-05-13-01.png

2. Attributesの追加

Box
2022-05-13-2.png

Pokemon
2022-05-13-03.png

3. Relationshipの追加

Box
2022-05-13-04.png
boxNoを主キーとして設定します。

Pokemon
2022-05-13-05.png
boxNoを外部キーとして設定します。

関係性の設定

Box
2022-05-13-06.png
1つのボックスには複数のポケモンを預けることができます。
なのでTo Many(1対多)に設定します。

Pokemon
2022-05-13-07.png
ポケモンは1つのボックスにだけ預けることができます。
なのでTo One(1対1)に設定します。

以上でCoreDataの設定は完了です。

データベースの使い方

関係する部分だけを載せています。
いないとは思いますが、他の部分が気になる方はGitHubのこちらのリポジトリに保存していますのでよかったら見て下さい。
(独学だから誰か見て評価して欲しい。。)

データの保存

RegistPokemonView.swift
import SwiftUI

struct RegistPokemonView: View {
    @Environment(\.colorScheme) private var colorScheme
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Box.boxNo, ascending: true)],
        animation: .default)
    private var boxs: FetchedResults<Box> //ボックスデータの呼び出し
    @State var boxNo: Box? //ピッカーで選択したボックスを格納
    let pokemon: PokemonJSONModel //ポケモンの情報
    
    var body: some View {

    /*省略*/

    }
    
    private func saveCoreData() { //預けるボタン押下時に実行
        if let box = box {
            let newPokemon = Pokemon(context: viewContext)
            newPokemon.id = UUID()
            newPokemon.name = pokemon.name
            newPokemon.pokedexNo = Int64(pokemon.no)
            newPokemon.boxNo = box //ポケモンとボックスの紐付け
            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }
}

ボックスのデータは予め用意しています。
データの紐付けは代入操作で行います。
2022-05-13-08.png
このとき、boxNoの型はBox?型になっていました。
Int型じゃなかった。手書きの図のイメージであってるのか不安。)

UI部分は省略しましたがこんな感じです。
2022-05-13-09-A.png
預けるボタンを押すとボックスに追加されます。
2022-05-13-10-A.png
2022-05-13-11-A.png

データの更新と削除

import SwiftUI

struct EditPokemonView: View {
    @Environment(\.colorScheme) private var colorScheme
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Box.boxNo, ascending: true)],
        animation: .default)
    private var boxies: FetchedResults<Box>
    @State private var boxNo: Box? //変更先のボックスを格納
    let pokemon: Pokemon //ポケモンの情報

    var body: some View {

    /*省略*/

    }

    private func saveCoreData() { //保存ボタン押下時に実行
        do {
            pokemon.boxNo = boxNo //変更先のボックスを代入
            try viewContext.save() //保存(更新)処理
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
    }

    private func deleteCoreData() { //逃がすボタンを押下時に実行
        viewContext.delete(pokemon) //削除処理
    }
}

更新時はPokemon.boxNoに別のBoxを代入してやればOKです。
.save()メソッドの呼び出しは忘れずに。

削除時は.delete(_:)メソッドの呼び出しだけでOKです。
この時ポケモンのデータがなくなるだけで、紐付いているボックスはなくなりません。

UIはこんな感じ。
2022-05-13-12-A.png

保存を押すとボックスを移動します。
2022-05-13-13-A.png
逃がすを押すといなくなります。。
2022-05-13-14-A.png

さいごに

今回はCoreDataでの関係データベース構築についてまとめてみました。
学びたてなので間違っていればご指摘お願いします。
最後までご覧いただきありがとうございました。

参考記事・書籍

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9