#目次
SwiftでRealmを使う時のTips まえがき
SwiftでRealmを使う時のTips(1) アクセサとエンティティ編
SwiftでRealmを使う時のTips(2) 生成とオートインクリメント編
SwiftでRealmを使う時のTips(3) NSPredicate編
アクセサ(DAO)とエンティティ(DTO)
データを扱うときは DAO
と DTO
という設計概念がありますね
厳密に正しいかどうかわかりませんが
ざっくりいうと「データを管理するヤツ」 と 「データそのもの」 は分離させる設計概念です
まぁ、健全なみなさんはちゃんとやってますよね・・・
これがたまにごっちゃにして書いている人がいるので
たまにソースを読んでてこちらもごっちゃになります
Realm自体には、こいつらを分離させるためのクラス体系はありません
なので、最初に自分で分離させておくことは少なくとも大事だと感じました
public class NBRealmEntity: RealmSwift.Object {
public static let IDKey = "id"
public static let CreatedKey = "created"
public static let ModifiedKey = "modified"
public dynamic var id : Int64 = 0 // = NBRealmEntity.IDKey
public dynamic var created = NSDate() // = NBRealmEntity.CreatedKey
public dynamic var modified = NSDate() // = NBRealmEntity.ModifiedKey
public override static func primaryKey() -> String? {
return NBRealmEntity.IDKey
}
}
import UIKit
import RealmSwift
public class NBRealmAccessor<T: NBRealmEntity> {
public typealias Entity = T
public var realm: Realm { return try! Realm() }
public init() {}
}
実装は上記のとおり2種類のクラスを用意します
ちなみにプレフィックスのNB
は自分の屋号からとってきたもので特に意味はありません
(外してもらってもいいです)
##エンティティ
データそのものを指すクラスは "エンティティ"
という名前にしています
他にも「オブジェクト」や「VO」「データ」「レコード」といった名前で
呼ぶ人もおられると思いますが、
ここではそのように名づけました
ID
を Int64
型にしていますが
よほどのことがない限りはInt
でもリソースの枯渇はないと思います
なので Int64
型 にこだわる必要はまったくないですが
ここではそのままにしています
##アクセサ
データを管理するクラスは "アクセサ"
という名前にしています
基底クラスでジェネリクスをとらせてますので
こいつは「あるエンティティ専用のアクセサ」として使うことができます
こんな感じですね
class UserEntity: NBRealmEntity {
// something
}
class UserAccessor: NBRealmAccessor<UserEntity> {
// something
}
UserAccessor
は UserEntity
に関するお仕事しかしないと
これで決めてやったも当然です
責務が狭まったこのクラスは、これであまりソースが散らかることがなくなります (本当かな?)
で、このアクセサは、狭義のモデルクラスになります
オブジェクトの死滅が早いコントローラに、モデルを所持させてはよくないです
ゆえに、呼び出しは下記のように実装すべきですねぇ
// こちらはダメな例
class ViewController: UIViewController {
public override func viewDidLoad() {
super.viewDidLoad()
let userAccessor = UserAccessor()
userAccessor.hoge()
}
}
// こういう感じにしておきたい
class Model {
static let userAccessor = UserAccessor()
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Model.userAccessor.hoge()
}
}
##両者の関係性
ここでエンティティとアクセサの両者を使う時のルールを確認します
- エンティティは必ずアクセサによって作られる
let user = UserEntity()
みたいなことができるのは唯一アクセサクラスだけというのを徹底します
たとえば、コントローラやビューに書いていては行けませんし、
モデルクラスであっても無関係な処理をしてるクラスでは絶対にインスタンス化をしません
これで 「UserEntity
をうんぬんかんぬんしてるってことは・・・、UserAccessor
だ!」と
メンテナンスの時に安心できますよね
- エンティティをデータベースに保存するのは必ずアクセサ
エンティティはただの変数の器。データの固まり
こいつ自身が単独で恒久的データをいじってしまうのはあまりよくないです
なかなか悩ませるのがRealmのオシャレな(?)機能である
リアルタイムアップデートというやつです
オブジェクトの値を変えると、KVOによってそのままデータベースも書き変わるというもの
まぁ便利なんだけど、逆に不便な場面が色々と出てきました
そこは場面によって使い分けも必要かと思いますが、
原則論としては、データベースの書き換えはアクセサ経由でないとやらせない
というルールをしっかりしておけば
CRUD
が散らかることが減るかなぁと個人的には思っております