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

Posted

技术标签:

【中文标题】如何在 NSManagedObjects 的集合(NSArray 或 NSSet)上设置 KVO【英文标题】:How to setup KVO on a Collection (NSArray or NSSet) of NSManagedObjects 【发布时间】:2012-03-20 22:11:04 【问题描述】:

我有一个 iPad 应用程序,它有一个实现 NSFetchedResultsControllerDelegateUITableViewController。 (主要使用斯坦福 ios 课程中的CoreDataTableViewController code。)

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

可以通过弹出框修改self.locations 的内容。我想设置某种观察,以便我的主要UITableViewController 可以观察存储在self.locations 中的对象的变化,并在必要时重新加载UISegmentedControl

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

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

【问题讨论】:

【参考方案1】:

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

[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];

执行相反的操作以停止观察托管对象上的键!

【讨论】:

感谢@Inafziger!这很有帮助。

以上是关于如何在 NSManagedObjects 的集合(NSArray 或 NSSet)上设置 KVO的主要内容,如果未能解决你的问题,请参考以下文章

如何按插入的顺序获取 NSManagedObjects?

如何将其他 NSManagedObjects 存储为 NSManagedObject 的属性

使用 setPropertiesToFetch 时将数据保存在 NSManagedObjects

如何不保留从 NSManagedObjectContext 检索到的 NSManagedObjects

如何将子上下文中的 NSManagedObjects 的两个不同实例合并为父上下文中的单个实例

ResKit:临时 NSManagedObjects