当一对多相关的 NSManagedObject 子类发生更改时,如何更新 NSManagedObject 子类?
Posted
技术标签:
【中文标题】当一对多相关的 NSManagedObject 子类发生更改时,如何更新 NSManagedObject 子类?【英文标题】:How to Update NSManagedObject subclass when a to-many related NSManagedObject subclass changes? 【发布时间】:2014-07-20 20:54:26 【问题描述】:我想在“Day”中保持正确的 emoAvg。以下是我希望完成的工作:
-
每当“情绪”与
“一天”……一天可以有很多情绪。
每当从“Day”中删除“Emotion”时,更新“Day”的 emoAvg
每当“Emotion”的情绪属性发生变化时,更新“Day”的 emoAvg。
我想将所有这些代码保留在模型层中,并且我已经能够通过调用以下代码将情绪与日子联系起来,该代码在创建情绪时将日子附加到情绪上。
我无法为“Day”与“Emotion”的一对多关系编写自定义访问器。我被困在 Xcode 4.6.2 中,并且此版本中似乎不存在复制/粘贴自定义 ObjectiveC 访问器功能。
构建此代码的好方法是什么?
- (void)setDate:(NSDate *)date
[self willChangeValueForKey:@"date"];
[self setPrimitiveValue:date forKey:@"date"];
[self associateDay];
[self didChangeValueForKey:@"date"];
-(void)associateDay
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:self.date];
//Start of Day
[dateComponents setHour:0];
[dateComponents setMinute:0];
[dateComponents setSecond:0];
NSDate *startOfDay = [calendar dateFromComponents:dateComponents];
//NSLog(@"Start of Day: %@", [dateFormatter stringFromDate:startOfDay]);
//End of Day
[dateComponents setHour:23];
[dateComponents setMinute:59];
[dateComponents setSecond:59];
NSDate *endOfDay = [calendar dateFromComponents:dateComponents];
//NSLog(@"End of Day: %@", [dateFormatter stringFromDate:endOfDay]);
//Find all Day Entities that fall on the same calendar date
NSPredicate *datePredicate = [NSPredicate predicateWithFormat:@"date > %@ AND date < %@", startOfDay, endOfDay];
NSFetchRequest *fetchDays = [[NSFetchRequest alloc]initWithEntityName:@"Day"];
fetchDays.predicate = datePredicate;
NSManagedObjectContext *context = [(id)[UIApplication sharedApplication].delegate managedObjectContext];
NSArray *daysFound = [context executeFetchRequest:fetchDays error:nil];
if ([daysFound count] == 1)
Day *dayWithMatchingDate = [daysFound objectAtIndex:0];
self.day = dayWithMatchingDate;
NSLog(@"Found %d matching days",[daysFound count]);
if ([daysFound count] > 1)
NSLog(@"Found %d matching days...Something needs fixing",[daysFound count]);
if ([daysFound count] < 1)
NSLog(@"Found %d matching days...Making a new Day and associating it",[daysFound count]);
NSManagedObjectContext *context = [(id)[UIApplication sharedApplication].delegate managedObjectContext];
Day *newDay = [NSEntityDescription insertNewObjectForEntityForName:@"Day" inManagedObjectContext:context];
newDay.date = self.date;
self.day = newDay;
【问题讨论】:
【参考方案1】:我认为将Day
建模为数据模型的一部分不一定是个好主意。现有的日期属性应该足以用于选择、过滤和其他逻辑。
不过,您走在正确的轨道上。关键是覆盖设置器。您需要覆盖Emotion
和Day
中的以下设置器(我的提示:在情感Emotion+Additions
上创建一个类别,以将此代码与基本模型类分开)。
setEmotion
在Emotion
removeEmotionsObject
在Day
addEmotionsObject
在Day
例如
-(void)removeEmotionsObject:(Emotion)value
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"emotions"
withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[[self primitiveEmotions] removeObject:value];
[self didChangeValueForKey:@"emotions"
withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
有关这些访问器的更多详细信息,请参阅 Core Data Programming Guide 的 relevant section。
【讨论】:
蒙迪,感谢您的回复。在提出问题之前,我阅读了您链接的部分。你能解释一下“[[self primitiveEmotions] removeObject:value];”我不清楚该代码的来源。 每个托管对象attribute
都由setPrimitiveAttribute
等方法自动支持。 removeObject
是一个常规的 NSSet
实例方法。【参考方案2】:
我能够得到我要求工作的代码。 然而,这是一团乱麻,我认为最好使用 NSNotificationCenter 并观察相关对象的变化。 这是有效的代码。 必须给 Mundi 提供帮助以帮助我。
- (void)addEmotionsObject:(Emotion *)value
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"emotions" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveEmotions] addObject:value];
[self calculateEmotionalAverage];
[self didChangeValueForKey:@"emotions" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
- (void)removeEmotionsObject:(Emotion *)value
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"emotions" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[[self primitiveEmotions] removeObject:value];
[self calculateEmotionalAverage];
[self didChangeValueForKey:@"emotions" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
- (void)addEmotions:(NSSet *)value
[self willChangeValueForKey:@"emotions" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
[[self primitiveEmotions] unionSet:value];
[self calculateEmotionalAverage];
[self didChangeValueForKey:@"emotions" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
- (void)removeEmotions:(NSSet *)value
[self willChangeValueForKey:@"emotions" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
[[self primitiveEmotions] minusSet:value];
[self calculateEmotionalAverage];
[self didChangeValueForKey:@"emotions" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
-(void)calculateEmotionalAverage
float emotionalTotal = 0;
for (Emotion *emo in self.emotions)
if ([emo.emotion isEqualToString:@"Joy = 22"])
emotionalTotal += 22.0;
NSLog(@"%f",emotionalTotal);
【讨论】:
以上是关于当一对多相关的 NSManagedObject 子类发生更改时,如何更新 NSManagedObject 子类?的主要内容,如果未能解决你的问题,请参考以下文章
使用父 NSManagedObject 上的关系枚举子实体 VS 使用 NSFetchRequest
CoreData - NSManagedObject 子对象一次只存储在一个对象中
如何为一对多关系正确配置 Core Data 数据模型和 NSManagedObject?