我已经建立了一个带有一些字符串字段和一些数组字段的模型。模型保存如下:
- (void)saveLevel:(NSString*)level traps:(NSArray*)traps whirls:(NSArray*)whirls accels:(NSArray*)accels walls:(NSArray*)walls dest:(NSString*)dest jupiter:(NSString*)jupiter rating:(NSNumber*)pRating;
{
if (m_pMOC == nil)
// Retrieves the managed object context
NSManagedObject* pNewLevel = [NSEntityDescription insertNewObjectForEntityForName:@"Level" inManagedObjectContext:m_pMOC];
NSDate* pDate = [NSDate date];
// Must have these four attributes
[pNewLevel setValue:level forKey:@"Level_ID"];
[pNewLevel setValue:jupiter forKey:@"Ball"];
[pNewLevel setValue:pDate forKey:@"Creation_Date"];
[pNewLevel setValue:dest forKey:@"Destination"];
[pNewLevel setValue:pRating forKey:@"Rating"];
// Optional attributes
if ([traps count] != 0)
[pNewLevel setValue:traps forKey:@"Traps"];
if ([whirls count] != 0)
[pNewLevel setValue:whirls forKey:@"Whirls"];
if ([accels count] != 0)
[pNewLevel setValue:accels forKey:@"Accelerators"];
if ([walls count] != 0)
[pNewLevel setValue:walls forKey:@"Walls"];
NSError* pError;
if (![m_pMOC save: &pError])
// etc...
}
我有一个DataManager类来处理从/到Core Data的提取/保存,在Manager内部我已经验证了当我获取一个实体时,数组被提取,但当它被返回到调用的类时它,数组是零(字符串,另一方面,到达就好了)。这是获取代码和解析fetch中返回值的代码:
- (NSArray*) getLevelWithID:(NSString*)level
{
NSEntityDescription *pEntityDescription = [NSEntityDescription entityForName:@"Level" inManagedObjectContext:m_pMOC];
NSFetchRequest *pRequest = [[[NSFetchRequest alloc] init] autorelease];
[pRequest setEntity:pEntityDescription];
NSPredicate* pPredicate = [NSPredicate predicateWithFormat:@"Level_ID == %@", level];
[pRequest setPredicate: pPredicate];
NSError* pError;
NSArray* pLevels = [m_pMOC executeFetchRequest:pRequest error:&pError];
if (pLevels == nil)
{
NSLog(@"Could not find the level with Level_ID = %@",level);
abort();
}
NSArray* pAccels = [pLevels valueForKey:@"Accelerators"];
NSArray* pTraps = [pLevels valueForKey:@"Traps"];
NSArray* pWalls = [pLevels valueForKey:@"Walls"];
NSArray* pWhirls = [pLevels valueForKey:@"Whirls"];
return pLevels;
}
我在最后四个数组上设置了一个断点,它们中有对象,但是在检索它们的函数中(如下所示),它们是零。
- (void) initLevel:(NSArray*)pLevelObjects
{
Level* pLevel = [pLevelObjects objectAtIndex:0];
NSString* pJupiter = pLevel.Ball;
NSString* pDest = pLevel.Destination;
NSArray* pAccels = [pLevel valueForKey:@"Accelerators"];
NSArray* pTraps = [pLevel valueForKey:@"Traps"];
NSArray* pWalls = [pLevel valueForKey:@"Walls"];
NSArray* pWhirls = [pLevel valueForKey:@"Whirls"];
... (other initialization of the level) ...
}
我为此感到困惑。字符串值在那里,但数组不是。我最初尝试使用点符号(NSArray * pAccels = pLevel.Accelerators等),但结果相同。
想法?
编辑:从视图控制器调用initLevel:
- (void) startGameWithLevelID:(NSString*)pLevelID
{
NSLog(@"MyViewController - beginGameWithLevelID");
NSArray* pLevel = [[DataManager getDataManager] getLevelWithID:pLevelID];
if (pLevel == nil || [pLevel count] == 0)
{
NSLog(@"Didn't retrieve any level with id %@", pLevelID);
abort();
}
else
{
CGRect newFrame = makeScreen([UIScreen mainScreen].applicationFrame);
GameBoard* pGB = [[GameBoard alloc] initWithFrame: newFrame];
pGB.m_pMyVC = self;
[pGB initLevel: pLevel];
[self.view addSubview: (UIView*)pGB];
[pGB release];
}
}
编辑:我新近将数组重新分解为与Level有一对一关系的独立实体;该级别与这些实体具有多对多关系。我还更改了名称以更好地遵守约定:所有属性和关系现在都以小写字母开头。我分别用a_和r_作为属性和关系的前缀。我在保存“ - [NSCFString _isKindOfEntity:]:无法识别的选择器发送到实例0x4d83120”时收到错误。这不是非常有用,但是当我发现问题时我会告诉你。目前,保存代码看起来像这样:
- (void)saveLevel:(NSString*)level traps:(NSArray*)traps whirls:(NSArray*)whirls accels:(NSArray*)accels walls:(NSArray*)walls dest:(NSString*)dest jupiter:(NSString*)jupiter rating:(NSNumber*)pRating;
{
if (m_pMOC == nil)
{ // Code to get the managed object context from the delegate
}
NSManagedObject* pNewLevel = [NSEntityDescription insertNewObjectForEntityForName:@"Level" inManagedObjectContext:m_pMOC];
NSManagedObject* pNewBall = [NSEntityDescription insertNewObjectForEntityForName:@"Ball" inManagedObjectContext:m_pMOC];
[pNewBall setValue:jupiter forKey:@"a_Bounds"];
NSManagedObject* pNewDest = [NSEntityDescription insertNewObjectForEntityForName:@"Dest" inManagedObjectContext:m_pMOC];
[pNewDest setValue:dest forKey:@"a_Bounds"];
NSDate* pDate = [NSDate date];
// Must have these four attributes
[pNewLevel setValue:level forKey:@"a_Level_ID"];
[pNewLevel setValue:pDate forKey:@"a_Creation_Date"];
[pNewLevel setValue:pRating forKey:@"a_Rating"];
[pNewLevel setValue:@"Bob Dole" forKey:@"a_CreatedBy"];
[pNewLevel setValue:pNewBall forKey:@"r_Ball"];
[pNewLevel setValue:pNewDest forKey:@"r_Dest"];
// Optional attributes
if ([traps count] != 0)
[[pNewLevel mutableSetValueForKey: @"r_Trap"] addObjectsFromArray: traps];
if ([whirls count] != 0)
[[pNewLevel mutableSetValueForKey: @"r_Whirl"] addObjectsFromArray: whirls];
if ([accels count] != 0)
[[pNewLevel mutableSetValueForKey: @"r_Accel"] addObjectsFromArray: accels];
if ([walls count] != 0)
[[pNewLevel mutableSetValueForKey: @"r_Wall"] addObjectsFromArray: walls];
NSError* pError;
if (![m_pMOC save: &pError])
{ // Error saving
}
else
{ // Successfully saved
}
}
再次感谢您的帮助,对于冗长的帖子感到抱歉,但我希望这会有助于其他核心数据新手(像我一样)学到一些东西。
FINAL EDIT:好的,所以在重构之后,我终于找到了一个解决方案来将数组保存为对象(尽管这是否是我不确定的最有效的方式)。下面是添加一堆“陷阱”的代码。传递给函数的数组是Trap的边界,它将被存储。然后用Level形成关系(注意它不必由Trap和Level设置,只需要其中一个,因为Core Data会采用另一种方式)。
if ([traps count] != 0)
{
for (NSString* pBounds in traps)
{
NSManagedObject* pNewTrap = [NSEntityDescription insertNewObjectForEntityForName:@"Trap" inManagedObjectContext:m_pMOC];
[pNewTrap setValue:pBounds forKey:@"a_Bounds"];
[pNewTrap setValue:pNewLevel forKey:@"r_Level"];
}
}
答案 0 :(得分:2)
在您的第一个代码段中,您在valueForKey:
上调用NSArray
,结果是一个数组,因为该代码迭代pLevels
,传递您的valueForKey:
参数到内部的每个对象并组合这些值。
这是NSArray
implements Key-Value Coding。
在第二段代码中,首先从数组中获取一个pLevel,然后在实体上执行valueForKey:
选择器,而不是在阵列上执行。结果就是那个特定对象的结果。
您的某些实体可能有这些字段,因此所有这些字段的组合结果都有一些值,但某些特定的值没有。
您说您在Core Data实体中保留了一个数组。你是怎样做的?没有特殊类型来保存数组,因此通常必须将其存储为二进制数据,并使用[NSKeyedArchiver archivedDataWithRootObject:array]
执行编码。可能是您的存储和提取不正确,因为您正在尝试将数组存储在非数组字段中。
您是否也遇到任何崩溃事件?