4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SwiftでRealmを使う時のTips(2) 生成とオートインクリメント編

Last updated at Posted at 2016-07-07

#目次

SwiftでRealmを使う時のTips まえがき
SwiftでRealmを使う時のTips(1) アクセサとエンティティ編
SwiftでRealmを使う時のTips(2) 生成とオートインクリメント編
SwiftでRealmを使う時のTips(3) NSPredicate編

#似非オートインクリメント

Realm にはオートインクリメント機能みたいなものはありません
整数型のIDを主キーにしてオブジェクトを扱うと色々と便利なので
「似非オートインクリメント」を前回に作ったアクセサクラスに追加します

public extension NBRealmAccessor {
    
    /// オートインクリメントされたID値
    public var autoIncrementedID: Int64 {
        guard let max = self.realm.objects(Entity).sorted(NBRealmEntity.IDKey, ascending: false).first else {
            return 1
        }
        return max.id + 1
    }
}

「似非」と呼んでいるのは
正しくは今あるエンティティの中で最も大きいIDに1を足したものを返している・・・からです
厳密に言うとスキーマなどで管理されているオートインクリメントではありません

しかしアプリでデータベースを扱う上で、この方法で支障が出ることはなかなかないです
厳密さが必要な場合は、要件に応じてここを作り変えればいいわけです

この計算プロパティを使ってエンティティを作成するメソッドを追加しました

public extension NBRealmAccessor {
    
    public func create() -> Entity {
        let ret = Entity()
        ret.id = self.autoIncrementedID
        return ret
    }
}

これでアクセサからエンティティを生成するときは
このように書くことが出来るようになりました

// 型推論により ": UserEntity" は不要ですが、わかりやすいように書いています
let user: UserEntity = UserAccessor().create()

しかし、この方法は問題が発生しました
下記のような場合の時です

for i in 0..<100 {
    let user: UserEntity = UserAccessor().create()
}

create()内の autoIncrementedID プロパティが
毎回データベースを見に行ってIDの最大値を取得しに行くので
これがオーバヘッドを生み出しました

さらに、データベースに未だ保存していない状態で次の新しいエンティティを作ろうとすると
当たり前ですが、変数useridは常に同じ値になります

なので、下記のように改修を行いました

public extension NBRealmAccessor {
    
    public func create(withID id: Int64? = nil) -> Entity {
        let ret = Entity()
        ret.id = id ?? self.autoIncrementedID
        return ret
    }
}

IDを指定することによって、データベースへのアクセスが走らないようにしました
ループ時は下記のように書くことでオーバヘッドは極端に減ります

let accessor = UserAccessor()
var id = accessor.autoIncrementedID

for i in 0..<100 {
    let user: UserEntity = accessor.create(withID: id)
    id += 1
}

オーバロードメソッドになったので
最初に書いた方法を崩すこともありませんね

let user: UserEntity = UserAccessor().create()
4
4
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
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?