核心数据:更改NSManagedObjectContextObjectsDidChangeNotification中的对象

时间:2013-10-11 15:43:45

标签: core-data

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

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

- (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;
         }];
    }
}

4 个答案:

答案 0 :(得分:3)

要修改Core Data对象而不触发更改通知,您可以使用 原始访问者方法,例如

[store setPrimitiveValue:@1000 forKey:@"distanceValue"];

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

但是你应该仔细考虑是否有任何不必要的副作用,因为 其他听众也将收到有关更改后值的通知。

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

答案 1 :(得分:1)

以下代码不在我的脑海中,未经过测试,但这就是我要去的方式。

@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;
         }];
    }
}

答案 2 :(得分:0)

示例如何查看NSManagedObject的子类。 YourPropertyName - 是你的班级

@implementation YourPropertyName

@dynamic stringValueOfYourProperty;//for example

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

然后在代码中的任何位置使用setStringValueOfYourProperty

答案 3 :(得分:0)

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

  1. didChange CoreData通知回调中,我将所有更新的对象保存在全局数组中。
  2. willSave CordData通知回调中,我修改了保存在第1点的对象
  3. didChange回调将再次被调用,willSave将被自动跳过
  4. didSave CoreData通知回调(如果需要)!