Iphone 核心数据-监视更改并注册本地通知

Iphone 核心数据-监视更改并注册本地通知,iphone,cocoa-touch,core-data,key-value-observing,Iphone,Cocoa Touch,Core Data,Key Value Observing,我对核心数据和KVC比较陌生,但我想了解一些关于注册核心数据对象更改侦听器的提示。情况如下: 我有一个NSManagedObject名为Patient,另一个名为medicing。患者可能有许多药物,而药物有startOn和endOn日期 我想以某种方式监听对所有medicing对象的endOn属性的更改。当发生更改时,我希望在iOS设备上安排本地通知。我以前使用过本地通知,但不知道在这种情况下将其代码放在哪里 我是否在应用程序委托中创建计划代码,并以某种方式注册应用程序委托以侦听对象中的更改?

我对核心数据和KVC比较陌生,但我想了解一些关于注册核心数据对象更改侦听器的提示。情况如下:

我有一个
NSManagedObject
名为
Patient
,另一个名为
medicing
患者
可能有许多
药物
,而
药物
startOn
endOn
日期

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

我是否在应用程序委托中创建计划代码,并以某种方式注册应用程序委托以侦听
对象中的更改?是否需要将其附加到
NSManagedObjectContext

这是怎么做到的?如有指点,将不胜感激


谢谢

对于键值观察,您需要一些实例来进行观察。有时,这可能是调用-setEndOn的同一个对象:药物治疗;有时候可能是别的原因。让我们假设你的应用程序有一个MedicalationManager类——创建了一个实例。并且,进一步假设MedicalationManager有一个实例方法-CreateMedicalationWithName: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;
        }
    }
或者类似的


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

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

此外,在下面的示例代码中,您还可以通过对存储此信息的患者创建瞬态属性来跟踪患者的聚合信息,如最快的startOn和最快的endOn。以下代码观察药物中endOn的变化,并为您提供更新患者上述瞬态“最快endOn”或“最快startOn”的能力


如何在
observeValueForKeyPath
内部获取
endOn
的值?使用
id newValue=[change objectForKey:NSKeyValueChangeNewKey]
使用
id newValue=[change objectForKey:NSKeyValueChangeNewKey]返回
null
返回
null
-如何获得结果?如果没有看到您的所有其他代码,我将无法推理,请尝试用源代码发布一个新问题。在我对上述答案的理解中,newValue没有得到nil
- (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
}