自定义 NSManagedObject 类从 NSOrderedSet 添加/删除对象
Posted
技术标签:
【中文标题】自定义 NSManagedObject 类从 NSOrderedSet 添加/删除对象【英文标题】:Custom NSManagedObject classes to add/remove Object from NSOrderedSet 【发布时间】:2012-12-10 05:33:05 【问题描述】:我正在学习 Cocoa,并按照 Aaron Hillegass 的书(第 32 章核心数据关系)中的一个示例进行操作,但无法使其适用于我自己的应用程序。
我有一个核心数据模型,它由一个与子对象具有一对多关系的父对象组成,但我的是一个有序集合,不像书中的,它是一个基本的 NSMutableSet。
每个对象(父对象和子对象)都有关联的 NSArrayControllers,我在 Interface Builder 中开发了一个基于文档的应用程序,其中包含按钮和绑定,用于从选定的父对象添加/删除子对象(在我的例子中称为感知器) (称为层)。一切正常。
现在我想拦截 add 和 remove 方法,以便在添加或删除子项时我可以自己编写代码。
在 Hillegass 的书中,他通过创建 NSManagedObjects 子类然后在代码中实现 addEmployeesObject: 和 removeEmployeesObject: 方法来做到这一点。所以这就是我尝试过的。
这是我由 XCode 编辑器创建的子类:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@class Network, Perceptron;
@interface Layer : NSManagedObject
@property (nonatomic, retain) Network *network;
@property (nonatomic, retain) NSOrderedSet *perceptrons;
@end
@interface Layer (CoreDataGeneratedAccessors)
- (void)insertObject:(Perceptron *)value inPerceptronsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromPerceptronsAtIndex:(NSUInteger)idx;
- (void)insertPerceptrons:(NSArray *)value atIndexes:(NSIndexSet *)indexes;
- (void)removePerceptronsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInPerceptronsAtIndex:(NSUInteger)idx withObject:(Perceptron *)value;
- (void)replacePerceptronsAtIndexes:(NSIndexSet *)indexes withPerceptrons:(NSArray *)values;
- (void)addPerceptronsObject:(Perceptron *)value;
- (void)removePerceptronsObject:(Perceptron *)value;
- (void)addPerceptrons:(NSOrderedSet *)values;
- (void)removePerceptrons:(NSOrderedSet *)values;
@end
这是我在 Layer.m 中根据教科书实现的两种方法:
- (void)addPerceptronsObject:(Perceptron *)value
NSLog(@"Network '%@' layer %lu is adding perceptron %lu", [[self network] name], [self indexInNetwork], [value indexInLayer]);
NSSet *s = [NSSet setWithObject:value];
[self willChangeValueForKey:@"perceptrons"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:s];
[[self primitiveValueForKey:@"perceptrons"] addObject:value];
[self didChangeValueForKey:@"perceptrons"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:s];
- (void)removePerceptronsObject:(Perceptron *)value
NSLog(@"Network '%@' layer %lu is removing perceptron %lu", [[self network] name], [self indexInNetwork], [value indexInLayer]);
NSSet *s = [NSSet setWithObject:value];
[self willChangeValueForKey:@"perceptrons"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:s];
[[self primitiveValueForKey:@"perceptrons"] removeObject:value];
[self didChangeValueForKey:@"perceptrons"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:s];
我将 NSLogs 放入其中,因此我确定它们不会被调用 - 当我添加/删除感知器对象时,控制台中没有任何内容。
ArrayController 在收到 add: remove: 消息时会做什么?是否将 addObject/removeObject 消息直接发送到集合?为什么在教科书示例中它会向父对象发送消息以删除子对象?为什么这里没有发生?有没有办法调试并找出答案?
谢谢
【问题讨论】:
【参考方案1】:比尔,
您正在覆盖由 Core Data 动态生成的方法。我怀疑您在查找表中的静态条目只是被覆盖了。这些方法与 @property
方法不同,后者会被覆盖。
从更大的意义上说,为什么要在此处插入代码?当对象被实例化时,有更好的支持方法为您的实现设计。您不妨检查一下-awakeFromFetch
和-awakeFromInsert
。
安德鲁
【讨论】:
谢谢adonoho。我会研究其他方法。我想插入代码,因为我必须在添加任何新感知器对象的同时创建额外的“孙子”对象。在本书的示例中,他们重写了该方法,因为他们想在删除之前检查即将被删除的员工对象是否是部门对象的“经理”。 Bill,虽然我们在 BNR 的朋友对事物非常了解,但请记住,他们通过两个棱镜看待事物:教育学和历史。有时这些并不是未来的最佳指南。我建议您创建自己的方法来进行检查,然后根据需要调用 Core Data 方法。安德鲁 好的,所以 awakeFromInsert 似乎可以完成这项工作。我确认每次添加新对象时都会调用它。但我还需要拦截任何 removeObject 请求,因为当从层中删除任何感知器对象时,我需要从核心数据中删除其他关联对象。 awakeFromInsert 等价于什么?另外,如果我在调用这些消息时添加/删除其他对象,我是否能够保持撤消/重做功能? Bill,Core Data 只是一个对象图管理器。它为您提供了对该图的许多访问点。这些是非常通用的方法。在我的应用程序中,当级联删除不足以进行图形管理时,我会从对象外部管理关系。-prepareForDeletion
是您正在寻找的方法。您的撤消/重做问题与您执行树管理的位置无关,这些是托管对象上下文的特征。安德鲁 P.S.如果您同意,请不要忘记接受此答案。以上是关于自定义 NSManagedObject 类从 NSOrderedSet 添加/删除对象的主要内容,如果未能解决你的问题,请参考以下文章
NSManagedObject - 跨线程设置自定义实例变量
如何使用创建的自定义 IBDesignable 类从情节提要中更改按钮的角半径
NSManagedObject;保留或加载到自定义 NSObject 中?