[Realm][Swift4対応 完全保存版] 5.データの更新と削除

はじめに

前回はRealmにおけるクエリについて説明をしました。

第5回目となる今回は、既存データの更新と削除をする方法について説明します。

過去記事は以下を参照ください。

環境

Xcode:9.4.1
Swift:4.1.2
Realm:3.7.4

目次

  1. 前準備
  2. データの更新
  3. データの削除
  4. Realmファイルの削除

1.前準備

前回と同様に、選手を表すPlayerモデルがある前提で説明をします。

参考までに、モデル定義のコードを以下に示します。
/// 選手モデル
class Player: Object {
    // 選手名
    @objc dynamic var name : String = ""
    // 身長(単位:m)
    @objc dynamic var height : Double = 0.0
    // 体重(単位:kg)
    @objc dynamic var weight : Double = 0.0
}

2.データの更新

2.1.データ更新の基本

前々回の記事「3.モデルオブジェクトの作成と書き込み」 にて addメソッドでデータを追加することを説明しました。

モデル定義から作成したインスタンスは、addメソッドを実行する手前までは「アンマネージドオブジェクト」と呼ばれ、通常のクラスと同様にプロパティの値を何度でも変更することができます。

addメソッド実行後は「マネージドオブジェクト」になるため、プロパティの値を変更しようとすると例外が発生してしまいます。

データの更新は、writeトランザクションの中で、直接プロパティ値を変更します。

以下にデータを更新する例を示します。

データの更新例
// (1)選手データの作成
let player = Player()
player.name = "J"
player.height = 198.0
player.weight = 99.0

// この時点ではアンマネージドオブジェクトなので
// プロパティ値の変更が可能
player.name = "Jordan"

// (2)データの追加
let realm = try! Realm()

try! realm.write {
    realm.add(player)
}

// ※データ追加後はマネージドオブジェクトになるので
// 以下を実行すると例外が発生する
//player.name = "Michael Jeffrey Jordan"

// (3)データの更新
try! realm.write {
    // プロパティ値を変更することで
    // Realmに反映される
    player.name = "Michael Jeffrey Jordan"
}

2-2.クエリ結果に対する更新

次にクエリ結果に対する更新方法について確認しましょう。

クエリについては、前回の記事「4.クエリによるデータの取得」を参照してください。

クエリを実行すると、Resultsクラスのインスタンスが返されます。このResultsクラスのインスタンスが持つプロパティを、writeトランザクション内で変更することで更新をすることができます。

以下に例を示します。この例ではPlayerのnameプロパティが「Michael Jeffrey Jordan」のデータを取得して、writeトランザクションの中で「Jordan」に更新しています。

クエリ結果に対する更新例
// (1)Realmインスタンスの生成
let realm = try! Realm()

// (2)クエリによるデータの取得
let results = realm.objects(Player.self).filter("name == 'Michael Jeffrey Jordan'").first

// (3)データの更新
try! realm.write {
    results?.name = "Jordan"
}

2-3.setValueメソッドを使用した更新

データの更新は、setValueメソッドを使用して行うこともできます。

setValueメソッドの書式を以下に示します。

setValue("更新後の値", forKey: "プロパティ名")

2-2.クエリ結果の更新」で示した例をsetValueメソッドに書き換えた例を以下に示します。

// (1)Realmインスタンスの生成
let realm = try! Realm()

// (2)クエリによるデータの取得
let results = realm.objects(Player.self).filter("name == 'Michael Jeffrey Jordan'").first

// (3)データの更新
try! realm.write {
    results?.setValue("Jordan", forKey: "name")
}

3.データの削除

データを削除するには、deleteメソッドかdeleteAllメソッドを使用します。

3-1.クエリ結果の削除

クエリで対象を絞り込んで削除するには delete メソッドを使用します。delete メソッドの引数には、クエリの結果(Results オブジェクト)を渡します。

以下に、クエリ結果を使用したデータの削除例を示します。この例では nameプロパティが「Michael Jeffrey Jordan」であるレコードを削除します。

クエリ結果を使用したデータの削除例
// (1)Realmインスタンスの生成
let realm = try! Realm()

// (2)クエリによるデータの取得
let results = realm.objects(Player.self).filter("name == 'Michael Jeffrey Jordan'")

// (3)データの削除
try! realm.write {
    realm.delete(results)
}

3-2.リレーションのあるデータの削除

1:1 や 1:Nのリレーションがある場合の削除も delete メソッドで行うことができます。

例として以下のような TeamモデルとPlayerモデルがあるとします。このモデルは、Teamが1に対してPlayerがNという関係にあるモデルです。

Bullsというチームに3人の選手が登録されていると仮定します。

Team
id name players
1 Bulls [list of Player]
Player
name height weight
HIRO 163 60.5
CHIHIRO 175 58
SHUHRI 170 61.2

上記のモデルから、Bullsの選手’HIRO’を削除するには、以下の手順を踏みます。

  1. チームBullsを取得する
  2. 1で取得したオブジェクトに対して、クエリで選手「HIRO」を取得する
  3. 2.で取得したオブジェクトをdeleteメソッドで削除する

以下にコード例を示します。

1:Nのデータを削除する例
let realm = try! Realm()

// (1)チーム「Bulls」を取得
let teams = realm.objects(Team.self).filter("name = 'Bulls'").first
// (2)選手「HIRO」を取得
let results = teams?.players.filter("name == 'HIRO'")

// (3)データの削除
try! realm.write {
    realm.delete(results!)
}

3-3.全データの削除

全てのデータを削除するには、deleteAllメソッドを使用します。ここでいう全てのデータとは、Realmファイル内に登録されている全てのデータを指します。よって1:1 や 1:N のリレーションの有無に関わらず全てのデータを削除します。ただしRealmファイル自体は残ります。

以下に、deleteAllメソッドによるデータの削除例を示します。

deleteAllメソッドを使用したデータの削除例
// (1)Realmインスタンスの生成
let realm = try! Realm()

// (2)全データの削除
try! realm.write {
    realm.deleteAll()
}

4.Realmファイルの削除

Realmに登録されたデータではなく、Realmファイルそのものを削除するには以下のコードを実行します。

Realmファイルの削除
let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
let realmURLs = [
    realmURL,
    realmURL.appendingPathExtension("lock"),
    realmURL.appendingPathExtension("note"),
    realmURL.appendingPathExtension("management")
]
for URL in realmURLs {
    do {
        try FileManager.default.removeItem(at: URL)
    } catch {
        // handle error
    }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください