我有两个实体,我也建模为类和核心数据模型实体/类看起来如下:
类:StateManager
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "StateManager.h"
#import "Constants.h"
@implementation StateManager
@synthesize deviceID, physicalID, applicationName, applicationVersion;
@synthesize userName, userPassword, server, port, client, language, protocol;
-(bool)checkCompleteness{
if (physicalID == nil) {
return false;
}
if (applicationName == nil) {
return false;
}
if (applicationVersion == nil) {
return false;
}
if (userName == nil) {
return false;
}
if (userPassword == nil) {
return false;
}
if (port == nil) {
return false;
}
if (server == nil) {
return false;
}
return true;
}
-(void)preserveState:(NSManagedObjectContext *)managedObjectContext{
// Step 1: Create Object
StateManager *inMemoryState = (StateManager *)[NSEntityDescription
insertNewObjectForEntityForName:ENTITY_STATE
inManagedObjectContext:managedObjectContext];
// Step 2: Set Properties
[inMemoryState setDeviceID:self.deviceID];
[inMemoryState setPhysicalID:self.physicalID];
[inMemoryState setApplicationName:self.applicationName];
[inMemoryState setApplicationVersion:self.applicationVersion];
//[inMemoryState setAutoRegister:[self getAutoRegister]];
[inMemoryState setUserName:self.userName];
[inMemoryState setUserPassword:self.userPassword];
[inMemoryState setServer:self.server];
[inMemoryState setPort:self.port];
[inMemoryState setClient:self.client];
[inMemoryState setLanguage:self.language];
[inMemoryState setProtocol:self.protocol];
// Step 3: Save Object
NSError *error;
if (![managedObjectContext save:&error]) {
NSLog(@"Unresolved Core Data Save error %@, %@", error, [error userInfo]);
exit(-1);
}
}
-(StateManager *)loadState:(NSManagedObjectContext *)managedObjectContext{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityState = [NSEntityDescription entityForName:ENTITY_STATE
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entityState];
NSError *error;
NSArray *items = [managedObjectContext
executeFetchRequest:fetchRequest error:&error];
if ([items count] > 0) {
StateManager *inDatabaseState = (StateManager *)[items objectAtIndex:0];
deviceID = [inDatabaseState valueForKey:@"deviceID"];
physicalID = [inDatabaseState valueForKey:@"physicalID"];
applicationName = [inDatabaseState valueForKey:@"applicationName"];
applicationVersion = [inDatabaseState valueForKey:@"applicationVersion"];
//autoRegister = [inDatabaseState valueForKey:@"autoRegister"];
userName = [inDatabaseState valueForKey:@"userName"];
userPassword = [inDatabaseState valueForKey:@"userPassword"];
server = [inDatabaseState valueForKey:@"server"];
port = [inDatabaseState valueForKey:@"port"];
client = [inDatabaseState valueForKey:@"client"];
language = [inDatabaseState valueForKey:@"language"];
protocol = [inDatabaseState valueForKey:@"protocol"];
[inDatabaseState release];
}
[fetchRequest release];
[entityState release];
[items release];
/*
deviceID = @"1234";
physicalID = @"12312";
applicationName = @"erwerw";
applicationVersion = @"applicationVersion";
//autoRegister = [inDatabaseState valueForKey:@"autoRegister"];
userName = @"userName";
userPassword = @"userPassword";
server = @"server";
port = @"port";
client = @"client";
language = @"language";
protocol = @"protocol";*/
return self;
}
-(void)dealloc{
[deviceID release];
[physicalID release];
[applicationName release];
[applicationVersion release];
[userName release];
[userPassword release] ;
[server release];
[port release];
[client release];
[language release];
[protocol release];
[super dealloc];
}
@end
类:InboundQueueState
#import "InQueueState.h"
@implementation InQueueState
@dynamic top;
@dynamic read;
@dynamic last;
@end
现在我正在尝试将这些对象数据从DB加载到我的应用程序中,如下所示:
如果查看类StateManager,您将看到一个方法loadState,它尝试使用托管对象上下文读取实体“StateManager”。此上下文已从主类传递给此类。
下面“InboundQueue”类中显示的另一个方法“readQueue”尝试遵循使用全局托管对象上下文加载实体“InboundState”的相同范例,但失败并显示以下错误:
错误:[NSFetchRequest objectID]:发送到的无法识别的选择器 实例0x3a1a300由于未捕获的异常而终止应用程序 'NSInvalidArgumentException',原因:'*** - [NSFetchRequest objectID]: 无法识别的选择器发送到实例0x3a1a300'
类别:InboundQueue
#import "InboundQueue.h"
#import <CoreData/CoreData.h>
#import "Constants.h"
#import "InQueueItem.h"
@implementation InboundQueue
-(int)last{
return [queueState last];
}
-(int)top{
return [queueState top];
}
-(int)read{
return [queueState read];
}
-(InboundQueue *)initInboundQueue:(NSManagedObjectContext *)managedObjectContext{
//load the inbound queue counters and initialize the inbound queue object with the values
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityState = [NSEntityDescription entityForName:INQUEUE_STATE
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entityState];
NSError *error;
NSArray *msgs = [managedObjectContext
executeFetchRequest:fetchRequest error:&error];
if ([msgs count] > 0) {
queueState = [msgs objectAtIndex:0]; //contains the values of the counters related to inbound queue at any point in time
}
[fetchRequest, entityState, msgs release];
return self;
}
-(NSMutableArray *)readQueue:(NSManagedObjectContext*) managedObjectContext{
//load the inbound queue counters and initialize the inbound queue object with the values
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityState = [NSEntityDescription entityForName:INQUEUE
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entityState];
NSError *error;
NSArray *queueContent = [managedObjectContext
executeFetchRequest:fetchRequest error:&error];
[queueData setArray:queueContent];
[fetchRequest, entityState, error release];
return queueData;
}
-(void)confirm:(int)msgID managedObjectContext:(NSManagedObjectContext*) managedObjectContext{
if (msgID < [queueState top]) {
return;
}
if (msgID > [queueState last]) {
return;
}
//remove items from queue which are lower than the confrmed message ID
for (InQueueItem *item in queueData) {
int currentMsgId = [item MSG_ID];
if ( currentMsgId <= msgID) {
//delete the item from queue and adjust counters
[queueData removeObject:item];
}
}
[queueState setTop:(msgID + 1)];
if ([queueState read] < [queueState top]) {
[queueState setRead:[queueState top]]; //realign the top counter
}
//persist the changes from context to database
NSError *error;
if (![managedObjectContext save:&error]) {
NSLog(@"Unresolved Core Data Save error %@, %@", error, [error userInfo]);
exit(-1);
}
}
-(void)add:(InQueueItem *)item managedObjectContext:(NSManagedObjectContext*) managedObjectContext{
//validate the message id
if (([queueState last] > ([item MSG_ID] - 1))) {
//ignore this message since we have already received a message with this message id
}else if (([queueState last] < ([item MSG_ID] - 1))) {
//raise an invalid message ID exception => data loss
}else {
if ([queueState last] == 0) {
//need to initialize counters as this is the first entry
[queueState setTop:[item MSG_ID]];
[queueState setLast:[item MSG_ID]];
}else {
//increment last
[queueState setLast:([queueState last] + 1)];
}
//now insert the item into queue
[queueData addObject:item];
}
//persist the changes from context to database
NSError *error;
if (![managedObjectContext save:&error]) {
NSLog(@"Unresolved Core Data Save error %@, %@", error, [error userInfo]);
exit(-1);
}
}
-(void)dealloc{
[queueData release];
[queueState release];
[super dealloc];
}
@end
我的理解是,相同的托管对象上下文可以加载数据模型的所有对象并允许操作,但我不确定为什么在我的情况下它只适用于一个对象。
答案 0 :(得分:4)
每个实体不需要单独的ManagedObjectContext。无论模型包含多少实体,ManagedObjectContext都会控制整个模型的整个对象图。 (您可以创建多个上下文但不能处理多个实体。)
如果你的A fetch正在踩到你B提取,那么你很可能没有正确配置你的B提取。你是否试图重复使用你为A创建的获取?
Fetches非常独特。每个提取都是单独配置的,您不应该将它们重用于其他实体或更改其提取参数(尽管该类不强制执行此操作。)
您应该初始化B的完全独立的抓取。
根据您发布的代码和错误的详细信息,我认为问题很可能是您没有为InQueueState
课程返回正确的实体说明。
我建议记录返回的实体:
NSEntityDescription *entityState = [NSEntityDescription entityForName:INQUEUE
inManagedObjectContext:managedObjectContext]
确保它不是零。
您(作为标准练习)还需要在使用之前检查NSArray *queueContent
是否为空或空。
此外,这一行:
[fetchRequest, entityState, error release];
您不需要释放entityState也不需要发生错误,因为您不会初始化或创建任何一个,而只是保留对从其他对象返回的引用。