Realmで日記アプリを作った時の備忘録 (Swift)

# はじめに
Realm×FSCalendarで日記アプリを作ってみたのでその時の備忘録を残そうかと.

# プロジェクト
[Realm×FSCalendarで日記アプリを作ってみた](https://github.com/fummicc1-sub/RealmSample_Swimee1117)

# 環境
- Realm 3.11.1
- Swift 4.2
- Xcode 10.1

# Realmとは?
モバイル向けNoSQLデータベースです.
NoSQLとは言葉の通り**SQLではないデータベース**のこと(Not Only SQL)です.
SQLといえばテーブルを作ってカラムを宣言してダミーのデータをあらかじめ用意しておいて...と複雑な手順が必要ですよね (SQLロクに触ったことないので詳しくはわかりませんが...)
SQLの問題点を解決したのがNoSQLだそうです.
ちなみに名前のとうりNoSQLの定義は大雑把でそのためNoSQLにもいくつか種類があるのですが,

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f34353235332f66306566353763652d356432662d343965652d653439352d6238346631356365333863662e6a706567.jpeg](https://qiita-image-store.s3.amazonaws.com/0/300444/253fac93-6aae-f47e-9ba6-eaffae8c4323.jpeg)

この図で言うとカラム指向型にRealmは当たると考えています.間違いがあればご指摘願います.

カラム指向型とは
> - カラム指向型
>     - 一般の行指向型DBと同様に表の構造を持ちつつ、カラム単位でデータを保持する。
>     - 行指向では苦手な列単位の大量集計、大量更新が得意。
> 
> 引用: [NoSQLについて勉強する。](ttps://qiita.com/t_nakayama0714/items/0ff7644666f0122cfba1)

とのことです.

# SwiftでのRealmの３つのルール基礎編

## 1. Realmのインスタンス生成時にキャッシュが参照される

```swift
let realm = Realm()
```

Realmのデータベースはこのように作成しますよね
Realmはこの時点でキャッシュが作成されるのでもう一度新たにインスタンスを作成した時に同じインスタンスを参照します.

```swift
let realm = try! Realm() //Realmのデータベースを作成

let realm2 = try! Realm() //Realmのデータベースを作成. ここのrealm2はrealmと同等のrealm
```

## 2. データの変更は`realm.write`メソッドの中で書かないといけない

[Realm×FSCalendarで日記アプリを作ってみた](https://github.com/fummicc1-sub/RealmSample_Swimee1117)のコードを参考にすると

```swift
let diary = Diary()
diary.title = "Hello World!"
try! realm.write {
    realm.add(diary)
}
```

このようにトランザクション内でデータベースへの更新処理を書かないといけないといけないようです.

そんなに気にしなくて大丈夫で一旦こういうものだと言う認識でいいと思います.

また、Realmのデータ更新はディスクの領域が足りなくなった時などにエラーから回復することを想定し`try`で書いているようです.

## 3. Realmの`Object`クラスのプロパティには`@objc dynamic`を先頭につける

これもルールなんだと言う認識でいいと思います.
以下のように書きます.

```swift
class Diary: Object {
    
    @objc dynamic var title: String = ""
    @objc dynamic var content: String = ""
    @objc dynamic var date: Date!
}
```

# SwiftでのRealmの2つのルール応用編

## 1. StandAloneなオブジェクトはrealmの更新を`realm.write`のなかで書かなくてOK

- StandAloneなオブジェクトの例

```swift
let diary = Diary()
// データの更新
diary.title = "new title" // 落ちない
```

- StandAloneではないオブジェクトの例

```swift
let diary = realm.objects(Diary.self).first!
// データの更新
diary.title = "new title" // 落ちる
```

このように**Realmデータベースに紐づいていないオブジェクト**をStandAloneといいます.

## 2. カラムの変更をしたらマイグレーションをしないといけない

書き方があるのでそれを紹介します.

```swift
let config = Realm.Configuration(schemaVersion: 0, migrationBlock: { (migration, version) in
    if version < 0 {
    }
})

Realm.Configuration.defaultConfiguration = config
```

これを`AppDelegate`の`didFinishLaunchingWithOptions`を引数としているメソッドに書いてあげてください.

カラムを更新したら`schemaVersion`の数を今の数字より大きくしてあげてください.

こんな感じになります.

```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
    //MARK: - migrationのコード
    let config = Realm.Configuration(schemaVersion: 0, migrationBlock: { (migration, version) in
        if version < 0 {
        }
    })

    Realm.Configuration.defaultConfiguration = config
    //MARK:-
        
    return true
}
```

# 最後に
以上でまとめを終わります.

最後まで読んでいただきありがとうございました〜

# 参考記事
- [NoSQLについて勉強する。](ttps://qiita.com/t_nakayama0714/items/0ff7644666f0122cfba1)