1
1

More than 3 years have passed since last update.

[Swift]Realm Swift #3 トラブル対応

Last updated at Posted at 2020-05-10

iOS でRealm Swift を 利用し、サンプルを作成する際のトラブル内容と対応事項をメモします。

目次

・ Realm Swift#1 class
・ Realm Swift#2 sample
・ Realm Swift#3 issue

動作環境

Swift 5.0
Xcode 11.1

トラブル一覧

1。レルムにデータ追加失敗の時
2。複数カラムのプライマリーキーが作成したい場合
3。 レルム取得する際にアプリクラッシュされる場合

レルムにデータ追加失敗の時

StudentAccessor.swift
class Student: Object {
    @objc dynamic var studentId = ""
    @objc dynamic var name = ""
    @objc dynamic var age = 0
}
func add(obj :T) throws {
    let realm = try! Realm()
    try realm.write {
        realm.add(obj, update: .modified)
    }
}

下記のようにRLMExceptionエラーが起きる。 

realm-add-exception.png
理由 : 主キーが存在しないため、更新できません。

対応方法

対応① 主キーを設定すること。

※注意:https://realm.io/docs/swift/3.20.0/#models
主キーを宣言すると、オブジェクトを効率的に検索および更新でき、
各値に一意性を適用できます。
主キーを持つオブジェクトをレルムに追加すると、
主キーは変更できなくなります。

StudentAccessor.swift(Primarykey)
override public static func primaryKey() -> String? {
    return "studentId"
}

対応②:主キーが設定できない場合

StudentAccessor.swift(追加のみ)
try realm.write {
    //追加の場合
    //realm.add(obj, update: .modified)
    realm.add(obj)
}
StudentAccessor.swift(更新のみ)
let student = realm.getObjects.first
try realm.write {
    //更新の場合
    student?.name = "test"
    student?.age = 20
}

複数カラムの主キーが作成したい場合

Student.swift(NG)
class Student: Object {
    @objc dynamic var studentId = ""
    @objc dynamic var age = 0

    override public static func primaryKey() -> String? {
        return String(format: "%@_%d ", studentId,age)
    }

(NG) 理由:主キーは一つ項目であるため、
realm-multi-primary-key-error.png

対応: 主キー(customPrimaryKey)を新しく作成すること。

但し、不要な項目が追加されてしまう。

Student.swift(OK)
class Student: Object {
    @objc dynamic var studentId = ""
    @objc dynamic var age = 0
    @objc dynamic var customPrimaryKey = ""

    override public static func primaryKey() -> String? {
        return "customPrimaryKey"
    }

    convenience init(studentId: String, age: Int) {
        self.init()
        self.studentId = studentId
        self.age = age
        self.customPrimaryKey =  String(format: "%@_%d ", studentId,age)
    }

レルム取得する際にアプリクラッシュされる場合

RealmBaseDao.swift(NG)
func updateOnly(block:() -> Void ) throws {
    try realm.write(block)
}

原因 : 想定ですが、クロージャは解放されず、
レルムのトランザクションを完了されなっかた。

対応: @ escapingを付与すること。

・クロージャが外部から渡される場合、@ escapingが必須らしい。
・非同期処理の後にクロージャを実行する場合は、
@ escaping を引数で受け取るクロージャに付与しなければなりません。

RealmBaseDao.swift(OK)
func updateOnly(block: @escaping () -> Void ) throws {
    try realm.write(block)
}

参考

https://realm.io/docs/swift/3.20.0/
@escapingと@autoclosure

Index

≪ Realm Swift #2 サンプル

1
1
1

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