1
1

More than 1 year has passed since last update.

【Swift5】Realmでデータを保存する

Last updated at Posted at 2022-07-26

Realmとは

  • モバイル版のデータベース管理システム
  • 公式ドキュメントはこちら

メリット

  • ライブラリRealmSwiftを使用すると、アプリのモデルレイヤーで高速かつ効率的に記述できる。
  • Realm Stadioアプリでデータベース管理ができる。
  • データの保存、削除、検索などデータを操作しやすい
  • アプリ内にデータを保存しているので、オフラインでも動くし、サーバーの負荷軽減にもつながる。

デメリット

  • Structやenumが使えない。書き方に工夫が必要。
  • Realm特有の仕様があるから思わぬとこでハマる。List型とか

Realmの導入

  • pod installする
pod 'RealmSwift'

実装

  • 今回は、PersonモデルとPokemonモデルを用意し、Personモデルに入っているPokemonモデルの配列にHitokageとZenigameとFusigidaneのデータを入れ、データがきちんとアプリ内に保存されているかログ出力で確認することを目標にします。

1.簡単にUIを作る

  • とりあえずUIButton並べる。

2.Model作成

Pokemon.swift
import RealmSwift

@objcMembers
class Pokemon: Object {
    dynamic var id = 0
    dynamic var name = ""
}
Person.swift
import RealmSwift

@objcMembers
class Person: Object {
    dynamic var id = 0
    dynamic var name = ""
    var pokemon = List<Pokemon>()
}

3.ViewControllerの作成

ViewController.swift

import UIKit
import RealmSwift

class ViewController: UIViewController {

    let person = Person()
    let realm = try! Realm()

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func tapHitokageButton(_ sender: Any) {
        let pokemon = Pokemon()
        pokemon.id = 1
        pokemon.name = "ヒトカゲ"

        try! realm.write {
            realm.add(pokemon)
            person.pokemon.append(pokemon)
            realm.add(person)
        }
    }

    @IBAction func tapZenigameButton(_ sender: Any) {
        let pokemon = Pokemon()
        pokemon.id = 2
        pokemon.name = "ゼニガメ"

        try! realm.write {
            realm.add(pokemon)
            person.pokemon.append(pokemon)
            realm.add(person)
        }
    }

    @IBAction func tapFusigidaneButton(_ sender: Any) {
        let pokemon = Pokemon()
        pokemon.id = 3
        pokemon.name = "フシギダネ"

        try! realm.write {
            realm.add(pokemon)
            person.pokemon.append(pokemon)
            realm.add(person)
        }
    }

    @IBAction func tapConfirmButton(_ sender: Any) {
        let resultPokemon = realm.objects(Pokemon.self)
        print(resultPokemon)
        let resultPerson = realm.objects(Person.self)
        print(resultPerson)
    }
}



完成

動作確認手順

  • 1 ヒトカゲボタン→ゼニガメボタン→フシギダネボタン→手持ちのポケモン確認ボタンを順番に押す
  • 2 ログ出力確認↓結果
Results<Pokemon> <0x7fbce80117c0> (
	[0] Pokemon {
		id = 1;
		name = ヒトカゲ;
	},
	[1] Pokemon {
		id = 2;
		name = ゼニガメ;
	},
	[2] Pokemon {
		id = 3;
		name = フシギダネ;
	}
)
Results<Person> <0x7fbce6f1c8f0> (
	[0] Person {
		id = 0;
		name = ;
		pokemon = List<Pokemon> <0x600000680a50> (
			[0] Pokemon {
				id = 1;
				name = ヒトカゲ;
			},
			[1] Pokemon {
				id = 2;
				name = ゼニガメ;
			},
			[2] Pokemon {
				id = 3;
				name = フシギダネ;
			}
		);
	}
)

こうして見事にrealm.objectsメソッドで、Personモデルの中にPokemonモデルのヒトカゲ、ゼニガメ、フシギダネのデータが保存されていることを確認できました。
ポケモンゲットだぜ!

はまった点

・PersonモデルのList型のPokemonの配列にうまくpokemonのidやnameなどのデータが入らなかった。
→List型とArray型の変換する?、LinkingObjectsを使う?プライマリーキーのidをoverrideする?とか色々調べて試したけどうまくいかなかった。

解決策:普通にappendするだけだった。

        try! realm.write {
            realm.add(pokemon)
            person.pokemon.append(pokemon)
            realm.add(person)
        }

pokemonModelのデータをRealmにaddで保存して、personモデルにアクセスしたList型のpokemon変数に保存したpokemonModelのデータをappendする。その後にpersonモデルもaddすれば保存できた。

1
1
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
1
1