コア データ ストアの各エンティティに NSDate プロパティを追加する以外に、任意のオブジェクトの変更日をプログラムで取得する方法はありますか?
7 に答える
いいえ、日付を追加して自分で管理する必要があります。管理対象オブジェクトでオーバーライドを使用-willSave
してタイムスタンプを更新できますが、willSave ループを引き起こさずに更新する方法については、NSManagedObject の API ドキュメントを参照し-willSave
てください (ドキュメントでは、タイムスタンプを更新する場合についても説明しています)。ドキュメントでは の使用についても言及NSManagedObjectContextWillSaveNotification
されていますが、タイムスタンプの設定が速すぎないようにするための単純なチェックよりも、設定が面倒な場合があります。
私は個人的に変更されたかどうかを確認し、updatedAt
変更された場合はもう触れません。willSave
このようにして、ループを破ります。
- (void)awakeFromInsert {
[super awakeFromInsert];
self.primitiveUpdatedAt = [NSDate date];
}
- (void)willSave {
[super willSave];
if(![self isDeleted] && self.changedValues[@"updatedAt"] == nil) {
self.updatedAt = [NSDate date];
}
}
このソリューションは、 model に dateUpated というプロパティがあることを前提としていることに注意してください。
これを個々のオブジェクトで処理する代わりに。私は通知を通じてこれを処理します。Apple のドキュメントでも、この方法が提案されています。
1. NSManagedObjectContextWillSaveNotification 通知に登録する
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willSaveContext:)
name:NSManagedObjectContextWillSaveNotification
object:nil];
2 更新されたオブジェクトごとに、observer メソッドで updatedDate のプロパティを設定します。
- (void)willSaveContext:(NSNotification *)notification{
NSManagedObjectContext *context = [notification object];
NSSet *updatedObject = [context updatedObjects];
for (NSManagedObject *managedObject in [updatedObject allObjects]) {
if ([[managedObject.entity propertiesByName] objectForKey:@"dateUpdated"]) {
[managedObject setValue:[NSDate date] forKey:@"dateUpdated"];
}
}
}
このQ/Aは、CoreDataで変更された日付の属性の設定を開始するのに役立ちました。その過程で、私はまた役立つかもしれないいくつかのヒントに到達しました:
(ヒント1:willSave再帰を回避する)
- willSaveループを回避する別の方法は、updatedObjectsを反復処理するコンテキストを保存するためのカスタムルーチンを作成して、dateModifiedプロパティを持つオブジェクトを探して設定することです。そのループの後に実際の呼び出しを
commitEditing
行います。save
willSaveをまったく気にしないでください。
(ヒント2:ライブアップデート—ただし、undoでは機能しません)
ユーザーに変更された日付をテーブルに表示するためにライブ更新が必要な場合は、objectValueForTableColumnデリゲートメソッド(iOSの場合はwillDisplayCell)の日付変更列のswitch-case(またはその他)でdateModifiedを設定することもできます。
そこで、その行のオブジェクトが更新されているかどうかをテストし、更新されている場合は、dateModifiedを設定します。
if (obj isUpdated)
小切手が非常に高価だとは思えません。ただし、これは、不必要に繰り返さないように、関連する列に対してのみ行うようにしてください。列に使用している文字列表現を返します。実際の変更時刻と設定された日付との明らかな差異を回避するために、時刻ではなく日付のみを表示してください。
これにより、ユーザーがテーブルを選択するたび、およびテーブルがリロードされるたびに、dateModifiedが更新されます。これは完全ではありません。ユーザーがテーブルに表示されていない属性を変更した場合、ユーザーが選択するまで列は更新されません。ただし、大規模なKVOスキームを実装するよりも、適度に応答性が高く、はるかに簡単です。
(テーブルに表示されない変更をキャッチするために、保存ルーチンで日付を設定する必要があります。)
UNDOの複雑さ:残念ながら、UNDOマネージャーは、テーブルデリゲートメソッドのdateModifedへの変更をそれ自体のイベントと見なします。その後、undoを呼び出すと、dateModifiedへの最後の変更が元に戻されます—何度も繰り返します。トラッカーを追加し、空でないchangedValuesディクショナリをチェックして、dateModifiedが事前保存時に一度だけ設定されるようにすることで、これを克服しようとしました。これは削除を元に戻すには機能しましたが、通常の編集には機能しませんでした。したがって、dateModifiedの事前保存のライブ更新を実行する簡単な方法はありません。
Swift でこれを行う簡単な方法が必要な場合:すべてのおよびプロパティを更新する単純なクラスに関するブログ投稿を書きました。この gistでクラス全体を見つけることができます。アプリケーション デリゲートのメソッドを呼び出すだけです。UpdateListener
updateDate
insertDate
UpdateListener.setupSharedInstance()
application(:didFinishLaunchingWithOptions:)