Core Dataを使っていて保存前に作成時刻や更新時刻を記録したい時にwillSaveのタイミングで記録できる。
とりあえずカスタムクラスを作成して、willSaveで普通にプロパティで設定してみる。
import Foundation import CoreData @objc(Item) public class Item: NSManagedObject { override public func willSave() { super.willSave() let now = Date() if createdAt == nil { createdAt = now } updatedAt = now } }
するとオプジェクト作成時にExceptionが出てクラッシュしてしまった。
プロパティを変更するとchangeフラグがセットされて再帰的にwillSave()が呼び出されクラッシュに至った。
createdAtはnilの時だけしかセットしないので、1回目はchangeフラグが立つが2回目は立たないので、このままでも問題ない。
updatedAtは毎回changeフラグが立ってしまうので問題がある。
試しにupdatedAt = nowの行をコメントアウトするとオブジェクト作成可能である。
@objc(Item) public class Item: NSManagedObject { override public func willSave() { super.willSave() let now = Date() if createdAt == nil { createdAt = now } // updatedAt = now } }
updatedAtはsetPrimitiveValue(:forKey:)で対応する。
setPrimitiveValue()はchangeフラグを立てない。
以前hasChangesにならないので悩んだがこれではっきりした。
@objc(Item) public class Item: NSManagedObject { override public func willSave() { super.willSave() let now = Date() if createdAt == nil { createdAt = now } setPrimitiveValue(now, forKey: "updatedAt") } }
今度はupdatedAtでも問題ない。
createdAtも2回呼び出されるのでsetPrimitiveValue()を使う方がいいだろう。
コードはこちら
CoreDataのwillSave()を使う際はsetPrimitiveValue(:forkey:)を使う · GitHub