我试图将我的NSManagedObject类子类化为封装我的get,set,save例程。该类使用自己的managedObjectContext和共享的persistentStoreCoordinator,因为这需要是线程安全的。
所有方法调用都没有问题,但是当我尝试执行save:方法时,我收到以下错误:
NSInvalidArgumentException', reason: '**-[MyEntity save:]: unrecognized selector sent to instance**'
附件是一个提供相同错误的简化版本。
这是子类的代码:
@interface XXMyEntity : MyEntity {
@private
NSManagedObjectContext * _managedObjectContext;
}
- (XXMyEntity *) init;
- (BOOL) save:(NSError **)error;
- (NSManagedObjectContext *) managedObjectContext;
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator;
@end
@implementation XXMyEntity
- (XXMyEntity *) init
{
self = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:[self managedObjectContext]];
return self;
}
- (BOOL) save:(NSError **)error
{
return [[self managedObjectContext] save:error];
}
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator
{
newCoreDataAppDelegate * appDelegate = (newCoreDataAppDelegate *)[[UIApplication sharedApplication] delegate];
return appDelegate.persistentStoreCoordinator;
}
- (void) dealloc
{
[_managedObjectContext release];
[super dealloc];
}
@end
实施:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
XXMyEntity * myEntity = [[XXMyEntity alloc]init];
myEntity.id = [NSNumber numberWithInt:1];
myEntity.title = @"My Title";
[myEntity save:nil];
[self.window makeKeyAndVisible];
return YES;
}
我还尝试将方法签名更改为其他类似saveEntity,假设我可能干扰了继承的方法但没有成功。
非常感谢任何帮助。
答案 0 :(得分:2)
我认为您的主要问题是您的init
方法要求对象已经拥有托管对象上下文,即使您从未分配过它。当然,你不能指定一个因为init
之前不存在自我。有点悖论。正如乔所指出的那样,你正在使用错误的实体。
您不应该以这种方式初始化托管对象子类。只需将它们插入到上下文中,就像通用托管对象一样,上下文将足够智能以返回正确的子类。如果要进行自定义,请使用awakeFromInsert
方法执行此操作。
答案 1 :(得分:1)
使用init函数的内存管理很差,就像在init之前调用alloc一样。此外,虽然您要更改值self,但它不会使其成为XXMyEntity
的类型,但它仍然是MyEntity
,这就是您收到错误的原因。
<强>更新强>
要使XXMyEntity工作,您需要打开xcdatamodel文件并将MyEntity类设置为XXMyEntity。另请阅读NSManagedObject的Subclassing Notes。
答案 2 :(得分:0)
让我发现它有些不对劲......
我假设MyEntity是NSManagedObject的子类。 XXXMyEntity有什么意义?
- (NSManagedObjectContext *) managedObjectContext;
self = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:[self managedObjectContext]];
[b managedObjectContext]
将返回不同的上下文。这意味着对b的任何更改可能无法正确获取;这很难说。+insertNewObjectForEntityForName:inManagedObjectContext:
的调用不会返回XXXMyEntity的实例(由TechZen识别)。+insertNewObjectForEntityForName:inManagedObjectContext:
也会使用+alloc
和-init
构建托管对象。你已经覆盖了-init
,所以它会导致无限递归。 newCoreDataAppDelegate * appDelegate = (newCoreDataAppDelegate *)[[UIApplication sharedApplication] delegate]
;
-[UIApplication delegate]
可能很愚蠢。如果线程是主线程,那么你可能想要使用相同的NSManagedObject上下文。如果您尝试使用Core Data在应用启动之间神奇地保留内容,并且您在主线程上执行了大部分处理,我会提出一些建议:
使用“便利构造函数”而不是覆盖-init:
+(myEntity所)实体 { NSManagedObjectContext * context = ...; MyEntity * entity = [NSEntityDescription insert ...]; 回报实体; }
有警告:
另请注意,在同一个线程中有多个MOC的情况是有意义的:如果您有一个带有取消按钮的“编辑”视图,您可以为编辑屏幕设置单独的MOC,如果用户取消则不保存。或者,我认为您可以使用单个MOC和NSUndoManager。
Core Data Programming Guide: Technology Overview给出了一个核心数据是否合适的列表;我怀疑你没有按照预期使用它。