2011-01-28 60 views
5

我對Core Data和KVC相對來說比較新,但是我希望有一些指針可以爲Core Data對象中的更改註冊監聽器。這裏的情況:核心數據 - 注意更改並註冊本地通知

我有一個NSManagedObjectPatient和另一個叫Medication。 A Patient可能有許多Medications,並且MedicationstartOnendOn日期。

我想以某種方式偵聽所有Medication對象的endOn屬性的更改。發生更改時,我想在iOS設備上安排本地通知。我以前曾使用過本地通知,但不知道在這種情況下將代碼放在哪裏。

我是否在應用程序委託中創建調度代碼,並以某種方式註冊應用程序委託以偵聽Medication對象中的更改?這是否需要附加到NSManagedObjectContext

這是如何完成的?指針將非常感謝!

謝謝!

回答

7

使用鍵值觀察,您需要一些實例來進行觀察。有時候可以是調用-setEndOn:on Medication的同一對象;有時它可能必須是別的東西。假設您的應用程序有一個MedicationManager類 - 其中創建了一個實例。而且,進一步假設MedicationManager有一個實例方法-createMedicationWithName:startOn:恩頓:是這樣的:

- (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; 
     } 
    } 

或類似的東西。

請注意,當您刪除藥物時,您希望刪除Observer ...此外,啓動您的應用程序時,您需要建立MedicationManager作爲現有藥物的觀察者。我認爲這可以像迭代所有藥物併爲每個藥物調用addObserver一樣簡單。如果您有很多藥物,那麼您可能希望以更「懶惰」的方式執行此操作(即在-awakeFromFetch中)。

+0

你會怎麼進去`observeValueForKeyPath的`endOn`價值的能力`? – daidai 2012-07-13 06:52:29

+0

使用`id newValue = [改變objectForKey:NSKeyValueChangeNewKey];`返回`空' – daidai 2012-07-13 06:53:45

3

當第一次從商店獲取對象以及創建對象時,您將不得不註冊觀察者。而不是在第一次獲取時必須遍歷所有條目(特別是在iPhone上出現錯誤時,如果未修改未提取的對象時可能會發生錯誤,那麼只需使用awakeFromFetch和awakeFromInsert消息。

此外,在下面的示例代碼中,您還可以通過在Patient上存儲此信息的瞬態屬性,像最早的startOn和最早的endOn一樣跟蹤Patient的聚合信息。下面的代碼遵守在服藥更改恩頓,爲您提供更新患者的上述瞬變「最快恩頓」或「儘快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 
}