【问题标题】:Core Data NSPredicate for relationships doesn't work after [context save][context save] 后关系的核心数据 NSPredicate 不起作用
【发布时间】:2015-08-28 17:41:59
【问题描述】:

我在 Core Data 中有两个实体(见下文),并使用 NSFetchedResultsController[NSPredicate predicateWithFormat:@"calendar.subscribed == 1"]; 来提取“事件”对象。

日历

  • 已订阅 (BOOL)
  • 事件(与“事件”的一对多关系)

事件

  • 日历(与“日历”的多对一关系)

一切正常,但如果我更改某些“日历”的subscribed 属性并将上下文保存在其他线程中,则不会调用controllerDidChangeContent

我可以强制重新获取吗?以及如何?

【问题讨论】:

  • 您可以删除您的谓词以接收对事件的所有更改,然后在您的委托方法中手动检查订阅标志。
  • 或者您可以从设置了订阅标志的日历实体中获取,然后在您的委托方法中获取所有关联事件

标签: ios objective-c core-data nsfetchedresultscontroller


【解决方案1】:

遗憾的是,FRC 仅监视作为获取主题的对象(在您的情况下为 Event)。因此它不会识别相关对象属性的更改,即使这些更改可能会影响谓词的评估方式。

一种解决方法(如果您可以忍受性能损失)是,当您更改 Calendar 对象的属性值时,将关联的 Event 对象上的值更改为其现有值 - 理论上没有变化,但是足以触发 FRC 重新评估该 Event 的谓词。

【讨论】:

  • 谢谢,但我想继续我的问题,看看我们是否可以有更好的解决方案。
  • 当然 - 我自己想要一个更清洁的解决方案。
【解决方案2】:

正如另一个答案中提到的,NSFetchedResultsController 只会获取对事件对象的更改,而不是日历。要强制刷新,您可以在调用“saveContext”后立即更新日历的订阅状态时发布 NSNotification:

[[NSNotificationCenter defaultCenter] postNotificationName:@"calendarSubscriptionUpdated" object:nil];

然后在要更新的类中添加一个观察者:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateEventData:) name:@"calendarSubscriptionUpdated" object:nil];

使用代码填充“updateEventData”(或您想调用的任何名称)方法以运行提取,然后您就可以开始了。

【讨论】:

    【解决方案3】:

    您可以在 Event 中添加观察者到 Calendar.subscribed

    -(void)awakeFromFetch {
      [ self addObserver:self
                forKeyPath:@"calendar.subscribed"
                   options:NSKeyValueObservingOptionNew
                   context:NULL ];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary *)change
                           context:(void *)context {
        if ([keyPath isEqualToString:@"calendar.subscribed"]) {
            [ self willChangeValueForKey:@"anyProperty" ];
            [ self didChangeValueForKey:@"anyProperty" ];
        }
    }
    
    -(void)willTurnIntoFault {
        [ super willTurnIntoFault];
        [ self removeObserver:self forKeyPath:@"calendar.subscribed" ];
    }
    

    使用事件的不动产名称代替“anyProperty”。在它起作用之前,我使用了相同的方法。

    【讨论】:

      猜你喜欢
      • 2013-05-03
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-18
      • 1970-01-01
      • 2012-03-08
      • 2011-04-10
      相关资源
      最近更新 更多