Core data 核心数据:NSManagedObjectContextObjectsIDChangeNotification中的更改对象

Core data 核心数据:NSManagedObjectContextObjectsIDChangeNotification中的更改对象,core-data,Core Data,是否可以在NSManagedObjectContextObjectsIDChangeNotification处理程序中更改托管对象的属性,而无需再次启动该处理程序? 我从服务器获取数据,RestKit将数据映射到核心数据。数据到达数据库后,我必须更改一些属性。 谢谢你的帮助 编辑: 这是我的密码。在循环中调用handledChangeNotification方法: - (void)addMyObserver { [[NSNotificationCenter defaultCenter]

是否可以在NSManagedObjectContextObjectsIDChangeNotification处理程序中更改托管对象的属性,而无需再次启动该处理程序? 我从服务器获取数据,RestKit将数据映射到核心数据。数据到达数据库后,我必须更改一些属性。 谢谢你的帮助

编辑: 这是我的密码。在循环中调用
handledChangeNotification
方法:

- (void)addMyObserver
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleDidChangeNotification:)
                                                 name:NSManagedObjectContextObjectsDidChangeNotification
                                               object:self.objectManager.managedObjectStore.mainQueueManagedObjectContext];
}

- (void)handleDidChangeNotification:(NSNotification *)notification
{
    NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
    NSSet *deletedObjects = [[notification userInfo] objectForKey:NSDeletedObjectsKey];
    NSSet *insertedObjects = [[notification userInfo] objectForKey:NSInsertedObjectsKey];

    // modifiedObjects with store entity:
    NSSet *modifiedObjects = [updatedObjects setByAddingObjectsFromSet:insertedObjects];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF isKindOfClass: %@", [MyStore class]];
    NSSet *modifiedStoreObjects = [modifiedObjects filteredSetUsingPredicate:predicate];

    if (modifiedStoreObjects.count > 0)
    {
        [modifiedStoreObjects enumerateObjectsUsingBlock:^(MyStore *store, BOOL *stop)
         {
             store.distanceValue = 1000;
         }];
    }
}

要在不触发更改通知的情况下修改核心数据对象,可以使用 基本访问器方法,例如

(请注意,此处需要对象值,标量值不起作用。)

但是如果没有任何不必要的副作用,你应该仔细考虑,因为 其他侦听器也不会被通知更改的值

另一种可能的解决方案是检查属性是否必须更改,
并仅在必要时进行修改。

示例如何查看
NSManagedObject的子类
YourPropertyName
-是您的类

@implementation YourPropertyName

@dynamic stringValueOfYourProperty;//for example

-(void)setStringValueOfYourProperty:(NSString *) _stringValueOfYourProperty
{
    [self willChangeValueForKey:@"stringValueOfYourProperty"];
    [self setPrimitiveValue: _stringValueOfYourProperty forKey:@"stringValueOfYourProperty"];
    [self didChangeValueForKey:@"stringValueOfYourProperty"];
}

然后在代码中的任何地方使用
setStringValueOfYourProperty

下面的代码是我脑子里想不出来的,没有经过测试,但我会这样做

@interface MyStoreCoordinator () {
    bool _changingValue;
}
@end

@implementation MyStoreCoordinator

- (void)addMyObserver
{
    _changingValue = NO;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleDidChangeNotification:)
                                                 name:NSManagedObjectContextObjectsDidChangeNotification
                                               object:self.objectManager.managedObjectStore.mainQueueManagedObjectContext];
}

- (void)handleDidChangeNotification:(NSNotification *)notification
{
    if (_changingValue)
    {
        return;
    }

    NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
    NSSet *deletedObjects = [[notification userInfo] objectForKey:NSDeletedObjectsKey];
    NSSet *insertedObjects = [[notification userInfo] objectForKey:NSInsertedObjectsKey];

    // modifiedObjects with store entity:
    NSSet *modifiedObjects = [updatedObjects setByAddingObjectsFromSet:insertedObjects];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF isKindOfClass: %@", [MyStore class]];
    NSSet *modifiedStoreObjects = [modifiedObjects filteredSetUsingPredicate:predicate];

    if (modifiedStoreObjects.count > 0)
    {
        [modifiedStoreObjects enumerateObjectsUsingBlock:^(MyStore *store, BOOL *stop)
         {
             _changingValue = YES;
             store.distanceValue = 1000;
             _changingValue = NO;
         }];
    }
}

我成功使用的一个解决方法是(我还没有注意到副作用。如果我错了,请告诉我)

  • didChange
    CoreData通知回调中,我将所有更新的对象保存在一个全局数组中
  • willSave
    CordData通知回调中,我修改了保存在第1点的对象
  • 将再次调用
    didChange
    回调,并将自动跳过
    willSave
  • didSave
    CoreData通知回调,如果需要
    您是否考虑过使用单独的MOC进行导入?这样你就可以观察环境来做出改变。我听说过,但我认为在这种情况下不建议这样做,正如你提到的,你可能会有副作用。我想,在检索到数据请求的响应后,我将手动进行距离更新。谢谢你的回答。这个中断会撤消吗?@malhal:我不知道。但是
    didChangeValueForKey
    会再次触发更改通知,这是OP试图避免的。如果应用程序是多用户的,没有
    didChangeValueForKey
    你就不会得到副作用?
    @interface MyStoreCoordinator () {
        bool _changingValue;
    }
    @end
    
    @implementation MyStoreCoordinator
    
    - (void)addMyObserver
    {
        _changingValue = NO;
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(handleDidChangeNotification:)
                                                     name:NSManagedObjectContextObjectsDidChangeNotification
                                                   object:self.objectManager.managedObjectStore.mainQueueManagedObjectContext];
    }
    
    - (void)handleDidChangeNotification:(NSNotification *)notification
    {
        if (_changingValue)
        {
            return;
        }
    
        NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
        NSSet *deletedObjects = [[notification userInfo] objectForKey:NSDeletedObjectsKey];
        NSSet *insertedObjects = [[notification userInfo] objectForKey:NSInsertedObjectsKey];
    
        // modifiedObjects with store entity:
        NSSet *modifiedObjects = [updatedObjects setByAddingObjectsFromSet:insertedObjects];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF isKindOfClass: %@", [MyStore class]];
        NSSet *modifiedStoreObjects = [modifiedObjects filteredSetUsingPredicate:predicate];
    
        if (modifiedStoreObjects.count > 0)
        {
            [modifiedStoreObjects enumerateObjectsUsingBlock:^(MyStore *store, BOOL *stop)
             {
                 _changingValue = YES;
                 store.distanceValue = 1000;
                 _changingValue = NO;
             }];
        }
    }