如何在NSManagedObjects的集合(NSArray或NSSet)上设置KVO

时间:2012-03-20 22:11:05

标签: ios core-data nsfetchedresultscontroller key-value-observing

我的iPad应用程序UITableViewController实现了NSFetchedResultsControllerDelegate。 (主要使用斯坦福iOS课程中的CoreDataTableViewController code。)

我有一个辅助模型对象(self.locations),它是Location个对象的数组,是NSManagedObjects的子类。此数组驱动UISegmentedControl的内容,用于过滤我的主fetchedResultsContoller

可以通过弹出窗口修改self.locations的内容。我想设置一些观察,以便我的主UITableViewController可以监视self.locations中存储的对象的更改,并在必要时重新加载UISegmentedControl

这也可能导致重新加载表中的主数据,所以我要小心不要在每次修改时重新加载。

我想我理解如何在单个NSManagedObject上设置KVO,但我不确定如何在数组中包含的对象上执行此操作。我知道我可以使用另一个NSFetchedResultsController,但是我的self.locations对象没有驱动第二个UITableView,所以我不确定它是否有意义。

1 个答案:

答案 0 :(得分:10)

如果您想知道是否添加,删除,替换或重新排序对象,那么观察一对多关系是非常简单的。实际上,它与普通对象完全相同:

[self addObserver:self
       forKeyPath:@"locations"
          options:0
          context:NULL];

然后执行以下操作以接收通知(部分从Apple文档复制):

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {

    if ([keyPath isEqual:@"locations"]) {
        // Your custom code here.
    }

    // Be sure to call the superclass's implementation *if it implements it*.
    [super observeValueForKeyPath:keyPath
                         ofObject:object
                           change:change
                           context:context];
}

不要忘记在某些时候停止观察:

[self removeObserver:self forKeyPath:@"locations"];

而且,虽然您没有问,但是如果您想知道关系中包含的任何对象是否已更改(而不仅仅是您的NSSet)在这里观看)然后你必须观察各个物体。

修改

根据您的评论,您确实希望观察单个对象。这对于“普通”对象来说相当简单,但是托管对象需要更多工作,因为您必须观察对象中的各个键,这看起来像这样:

- (void)observeManagedObject:(NSManagedObject *)myObject {
    NSArray *myObjectKeys = [[[myObject entity] attributesByName] allKeys];
    for (NSString *key in myObjectKeys) {
        [myObject addObserver:self 
                    forKeyPath:key 
                       options:0 
                       context:nil];
    }
}

然后你会观察数组中的所有NSManagedObjects:

for (NSManagedObject *object in myArray) {
    [self observeManagedObject:object];
}

反过来停止观察托管对象上的密钥!