在NSManagedObjectsDidChangeNotification创建无限循环后设置lastModificationDate属性

时间:2013-11-20 14:26:33

标签: ios objective-c core-data icloud uimanageddocument

我向所有实体添加了 lastModifiedDate 属性,以避免在将UIManagedDocument与iCloud同步时出现重复,我发现如果我使用离线设备创建新实体,可能会发生这种情况( iPad),同时,我使用另一个在线设备(iPhone)创建相同的实体。

我想在对象发生变化时设置此属性,因此我订阅了NSManagedObjectContextObjectsDidChangeNotification。我编写的用于设置lastModifiedDate的代码创建了一个无限循环,因为通过设置lastModificationDate属性,它创建了一个更改,NSManagedObjectContextObjectsDidChangeNotification将再次通知,等等......

有可能解决它吗?有没有更好的方法来实现我的目标?我应该将managedObjectContext子类化并覆盖willSave:吗?

//At init...

[[NSNotificationCenter defaultCenter] addObserver:applicationDatabase
                                             selector:@selector(objectsDidChange:)
                                                 name:NSManagedObjectContextObjectsDidChangeNotification
                                               object:applicationDatabase.managedDocument.managedObjectContext];


(void) objectsDidChange: (NSNotification*) note
{
  // creates an infinite loop
    NSDate *dateOfTheLastModification = [NSDate date];
    NSMutableArray *userInfoKeys = [[note.userInfo allKeys] mutableCopy];

    for(int i=0; i< userInfoKeys.count;i++){
        NSString *key = [userInfoKeys objectAtIndex:i];
        if([key isEqualToString:@"managedObjectContext"]){
            [userInfoKeys removeObject:key];
        }
    }

    for(NSString *key in userInfoKeys){
        NSArray *detail = [note.userInfo objectForKey:key];
        for (id object in detail){

            [object setValue:dateOfTheLastModification forKey:@"lastModifiedDate"];
        }
}

1 个答案:

答案 0 :(得分:7)

为避免无限循环,您可以使用。设置上次修改日期 原始访问者

[object setPrimitiveValue:dateOfTheLastModification forKey:@"lastModifiedDate"];

因为这不会引发另一次&#34;改变&#34;通知。但这也意味着 没有观察者会看到这种变化。

覆盖托管对象子类中的willSave会遇到同样的问题。 willSave的Apple文档声明:

  

例如,如果您设置了上次修改的时间戳,则应检查   您是否先前在同一个保存操作中设置它,或者   现有的时间戳不小于一个小的增量   当前时间。通常,最好一次计算时间戳   对于要保存的所有对象(例如,响应于   NSManagedObjectContextWillSaveNotification)。

所以你应该注册NSManagedObjectContextWillSaveNotification, 并在托管对象中的所有更新和插入的对象上设置时间戳 上下文。注册的方法可能如下所示:

-(void)contextWillSave:(NSNotification *)notify
{
    NSManagedObjectContext *context = [notify object];
    NSDate *dateOfTheLastModification = [NSDate date];
    for (NSManagedObject *obj in [context insertedObjects]) {
        [obj setValue:dateOfTheLastModification forKey:@"lastModifiedDate"];
    }
    for (NSManagedObject *obj in [context updatedObjects]) {
        [obj setValue:dateOfTheLastModification forKey:@"lastModifiedDate"];
    }
}

这假定您的所有实体都具有lastModifiedDate属性,否则 你必须检查对象的类。