核心数据 - 观察变化并注册本地通知

Posted

技术标签:

【中文标题】核心数据 - 观察变化并注册本地通知【英文标题】:Core Data - Watch for changes and register local notifications 【发布时间】:2011-01-28 22:26:12 【问题描述】:

我对 Core Data 和 KVC 比较陌生,但我想要一些关于注册侦听器以更改 Core Data 对象的指针。情况如下:

我有一个NSManagedObjectPatient,另一个叫Medication。一个Patient 可能有多个Medications,一个Medication 有一个startOnendOn 日期。

我想以某种方式监听所有 Medication 对象的 endOn 属性的更改。当发生更改时,我想在 ios 设备上安排本地通知。我以前使用过本地通知,但不知道在这种情况下将代码放在哪里。

我是否在 App Delegate 中创建调度代码并以某种方式注册 App Delegate 以监听 Medication 对象的变化?这需要附加到NSManagedObjectContext吗?

这是怎么做到的?指针将不胜感激!

谢谢!

【问题讨论】:

【参考方案1】:

使用 Key Value Observing,您需要一些实例来进行观察。有时这可能是调用 -setEndOn: on Medication 的同一个对象;有时它可能必须是别的东西。假设您的应用程序有一个 MedicationManager 类 - 其中一个实例被创建。并且,进一步假设 MedicationManager 有一个实例方法 -createMedicationWithName:startOn:endOn: 像这样:

- (Medication*) createMedicationWithName:(NSString*)medName startOn:(NSDate*)startDate endOn:(NSDate*)endDate
    
    //  Create and configure a new instance of the Compound entity 
    Medication *newMedication = (Medication *)[NSEntityDescription insertNewObjectForEntityForName:@"Medication"
                                                inManagedObjectContext:[self managedObjectContext]];
    [newMedication setName:medName];
    [newMedication setStartOn:startDate];
    [newMedication setEndOn:endDate];

    //  Set up KVO
    [newMedication addObserver:self
                    forKeyPath:@"endOn"
                    options:NSKeyValueObservingOptionNew
                    context:nil];

    return newCompound;
    


- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
                                                    change:(NSDictionary *)change 
                                                    context:(void *)context
    
    if ([keyPath isEqualToString:@"endOn"])
        
        //  ... schedule local notification on the iOS device for (Medication*)object.
        return;
        
    

或者类似的东西。

注意,当您删除一个 Medication 时,您会想要 removeObserver... 此外,在启动您的应用程序时,您需要将 MedicationManager 建立为现有 Medication 的观察者。我认为这可以像遍历所有药物并为每个药物调用 addObserver 一样简单。如果您有很多药物,那么您可能希望以更“懒惰”的方式(即,在 -awakeFromFetch 中)执行此操作。

【讨论】:

如何在observeValueForKeyPath 中获得endOn 的值? 使用id newValue = [change objectForKey:NSKeyValueChangeNewKey]; 返回null【参考方案2】:

当第一次从存储中获取对象以及创建对象时,您必须注册观察者。无需在第一次获取时遍历所有条目(这很容易出错,尤其是在 iPhone 上,当未保留的未修改获取的对象可能会出错时)只需使用 awakeFromFetch 和 awakeFromInsert 消息。

此外,在下面的示例代码中,您还可以通过在存储此信息的患者上创建临时属性来跟上患者的聚合信息,例如最快的 startOn 和最快的 endOn。下面的代码观察了 Medication 中 endOn 的变化,并让您能够更新患者的上述瞬态“soonest endOn”或“soonest startOn”

- (void)addMyObservers

    registeredObservers_ = YES;
    [self addObserver:self forKeyPath:@"endOn" options:NSKeyValueObservingOptionNew context:nil]; 


- (void)awakeFromInsert 

    // called when you create this object
    [super awakeFromInsert];
    [self addMyObservers];


- (void)awakeFromFetch

    // called when you fetch this old object from the store
    [super awakeFromFetch];
    [self addMyObservers];


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

    if([keyPath isEqualToString:@"endOn"]) 
    
        id newValue = [change objectForKey:NSKeyValueChangeNewKey];
        // someone changed endOn so do something with this "newValue"
        // check to see if the Patient needs the transient property for the soonest medication updated
        // update any local notification schedule 
    


// this is only required if you want to update the Patient's transient property for the soonest endOn or 
- (void)setPatient:(Patient *)patient

    [self willChangeValueForKey:@"patient"];
    [self setPrimitivePatient:patient];
    [self didChangeValueForKey:@"patient"];

    // check to see if the Patient needs the transient property for the soonest medication updated

【讨论】:

使用id newValue = [change objectForKey:NSKeyValueChangeNewKey]; 返回null - 我怎样才能得到结果? 如果没有看到您的所有其他代码,我将无法推理,请尝试使用源代码发布一个新问题。在我的上述答案版本中,newValue 没有得到 nil

以上是关于核心数据 - 观察变化并注册本地通知的主要内容,如果未能解决你的问题,请参考以下文章

iOS小技能:本地通知的机制

注册本地通知闹钟,备忘录

注册本地通知

注册本地和远程通知

从后台注册本地通知

iOS设计模式2 - 观察者模式_通知机制