我在Core Data上遇到了麻烦,现在让我疯了一天多了。当我使用Xcode退出我的应用程序时,我失去了所有核心数据关系。所有对象仍然在SQL数据库中,但它们之间的关系消失了。我看着这是最接近的东西:
Some CoreData relationships are lost after closing app
我尝试使用mutableSetValueForKeyPath:
if ([[NSString stringWithFormat:@"%@",[item mutableSetValueForKeyPath:@"clothing_type"]] isEqualToString:@"Top"])
return item;
但我得到:
'NSInvalidArgumentException',原因:'实体'ClothingItem'的NSManagedObjects不支持-mutableSetValueForKey:属性'clothing_type''
有人可以帮忙吗?以下代码是主要问题发生的地方。我设置衣柜,一切都很好。 getTop,getBottom和getShoes在视图等之间正常工作。即使应用程序进入后台并返回它也没关系。但我通过xcode退出应用程序,当我回来时我运行调试器并且衣柜就在那里,但是当我运行getTop,getBottom或getShoes时,它返回nil,因为@dynamic衣服是零。这是衣柜文件:
#import "Wardrobe.h"
#import "ClothingItem.h"
@implementation Wardrobe
@dynamic clothes;
- (ClothingItem*) getTop
{
for (ClothingItem *item in clothes){
if ([[item valueForKey:@"clothing_type"] isEqualToString:@"Top"])
return item;
}
return nil;
}
- (ClothingItem*) getBottom
{
for (ClothingItem *item in clothes){
if ([[item valueForKey:@"clothing_type"] isEqualToString:@"Bottom"])
return item;
}
return nil;
}
- (ClothingItem*) getShoes
{
for (ClothingItem *item in clothes){
if ([[item valueForKey:@"clothing_type"] isEqualToString:@"Shoes"])
return item;
}
return nil;
}
@end
这是我设置收藏夹的地方。我最初将它保存为多维NSMutableArray并将其存储在NSUserDefaults中但是当我返回时它又消失了。我想多维NSMutableArray无法以这种方式存储。所以我决定使用Core Data,这似乎是最合适的事情:
- (IBAction)saveCurrentAsFavorite:(id)sender {
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObject *top = nil;
NSManagedObject *bottom = nil;
NSManagedObject *shoes = nil;
UIAlertView *myAlert;
if (delegate.topClothesList.count > delegate.currentTopNumber){
top = [delegate.topClothesList objectAtIndex:delegate.currentTopNumber];
}
else {
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle: @"No Top!" message: @"Please select a top if you want to add to favorites!" delegate: nil cancelButtonTitle:@"Okie dokie!" otherButtonTitles:nil];
[myAlert show];
return;
}
if (delegate.bottomClothesList.count > delegate.currentBottomNumber){
bottom = [delegate.bottomClothesList objectAtIndex:delegate.currentBottomNumber];
}
else {
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle: @"No Bottom!" message: @"Please select a bottom if you want to add to favorites!" delegate: nil cancelButtonTitle:@"Roger!" otherButtonTitles:nil];
[myAlert show];
return;
}
if (delegate.shoesClothesList.count > delegate.currentShoeNumber){
shoes = [delegate.shoesClothesList objectAtIndex:delegate.currentShoeNumber];
}
else {
//shoes = nil;
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle: @"No Shoes!" message: @"Please select shoes if you want to add to favorites!" delegate: nil cancelButtonTitle:@"Will do!" otherButtonTitles:nil];
[myAlert show];
return;
}
// The old way of doing it where I saved it all in an NSMutableArray, but it wouldn't save into NSUserDefaults as a multidimensional NSMutableArray…
/* NSMutableArray *wardrobe = [[NSMutableArray alloc] initWithObjects:top, bottom, shoes, nil];
for (int i = 0; i < delegate.favoriteWardrobes.count; i++){
if ([[[delegate.favoriteWardrobes objectAtIndex:i] objectAtIndex:0] isEqual: [wardrobe objectAtIndex:0]] && [[[delegate.favoriteWardrobes objectAtIndex:i] objectAtIndex:1] isEqual: [wardrobe objectAtIndex:1]] && [[[delegate.favoriteWardrobes objectAtIndex:i] objectAtIndex:2] isEqual: [wardrobe objectAtIndex:2]]){
myAlert = [[UIAlertView alloc] initWithTitle: @"Wardrobe Already In Favorites!" message: @"Very nice choice, again! You like this wardrobe, so you should just buy it! Click the images so you could visit their sites and buy them!" delegate: nil cancelButtonTitle:@"Nice!" otherButtonTitles:nil];
[myAlert show];
return;
}
}
[delegate.favoriteWardrobes addObject:wardrobe];
// save information
NSArray *values = [[NSArray alloc] initWithObjects:delegate.selectedTopStyles, delegate.selectedBottomStyles, delegate.selectedShoesStyles, delegate.selectedSexes, delegate.selectedPrices, delegate.favoriteWardrobes, nil];
[values writeToFile:[self saveFilePath] atomically:YES];
//[[NSUserDefaults standardUserDefaults] setObject:delegate.favoriteWardrobes forKey:@"favoriteWardrobes"];
myAlert = [[UIAlertView alloc] initWithTitle: @"Wardrobe Added To Favorites!" message: @"Very nice choice! Awesome style! \n\nReminder: if you select View Favorities you can send this wardrobe to yourself and your friends!" delegate: nil cancelButtonTitle:@"Sweet!" otherButtonTitles:nil];
[myAlert show];
*/
// TRY DOING IT THE CORE DATA WAY
// need to fetch the Wardrobe objects and check their children to see if they match; and if any of these children do not exist within that wardrobe, skip it. If there is a wardrobe that contains all three then say wardrobe is already added
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:@"Wardrobe" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
[request setIncludesSubentities:NO];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:request error:&error];
ClothingItem *clothingTop, *clothingBottom, *clothingShoes;
for (Wardrobe *ward in fetchedObjects) {
clothingTop = [ward getTop];
clothingBottom = [ward getBottom];
clothingShoes = [ward getShoes];
if (([[clothingTop valueForKey:@"clothing_id"] isEqual:[top valueForKey:@"clothing_id"]]) && ([[clothingBottom valueForKey:@"clothing_id"] isEqual:[bottom valueForKey:@"clothing_id"]]) && ([[clothingShoes valueForKey:@"clothing_id"] isEqual:[shoes valueForKey:@"clothing_id"]])){
myAlert = [[UIAlertView alloc] initWithTitle: @"Wardrobe Already In Favorites!" message: @"Very nice choice, again! You like this wardrobe, so you should just buy it! Click the images so you could visit their sites and buy them!" delegate: nil cancelButtonTitle:@"Nice!" otherButtonTitles:nil];
[myAlert show];
return;
}
}
// if there's no case like that and this wardrobe is unique then do the following:
// Grab the Wardrobe entity
Wardrobe *newWardrobe = [NSEntityDescription insertNewObjectForEntityForName:@"Wardrobe" inManagedObjectContext:context];
/*ClothingItem* topCloth = (ClothingItem *) top;
ClothingItem* bottomCloth = (ClothingItem *) bottom;
ClothingItem* shoesCloth = (ClothingItem *) shoes;*/
// Instead of doing straight casting because that doesn't seem recommended, do more fetch requests to be extra careful
// We're looking to grab ClothingItems
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ClothingItem"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"clothing_id == %@", [top valueForKey:@"clothing_id"]];
[fetchRequest setPredicate:predicate];
error = nil;
fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
ClothingItem* topCloth = [fetchedObjects objectAtIndex:0];
predicate = [NSPredicate predicateWithFormat:@"clothing_id == %@", [bottom valueForKey:@"clothing_id"]];
[fetchRequest setPredicate:predicate];
error = nil;
fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
ClothingItem* bottomCloth = [fetchedObjects objectAtIndex:0];
predicate = [NSPredicate predicateWithFormat:@"clothing_id == %@", [shoes valueForKey:@"clothing_id"]];
[fetchRequest setPredicate:predicate];
error = nil;
fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
ClothingItem* shoesCloth = [fetchedObjects objectAtIndex:0];
// adding wardrobe to the clothes
[topCloth addWardrobeObject:newWardrobe];
[bottomCloth addWardrobeObject:newWardrobe];
[shoesCloth addWardrobeObject:newWardrobe];
// adding clothes to wardrobe
// adding individually just to see if it works this way; the NSSet below was working fine
[newWardrobe addClothesObject:topCloth];
[newWardrobe addClothesObject:bottomCloth];
[newWardrobe addClothesObject:shoesCloth];
//[newWardrobe addClothes:[NSSet setWithObjects:topCloth, bottomCloth, shoesCloth, nil]];
if ([context save:&error]) {
NSLog(@"The save was successful!");
} else {
NSLog(@"The save wasn't successful: %@", [error localizedDescription]);
}
//[delegate saveContext]; // does this help?
//[newWardrobe addClothesObject:[delegate.topClothesList objectAtIndex:delegate.currentTopNumber]];
//[newWardrobe addClothesObject:[delegate.bottomClothesList objectAtIndex:delegate.currentBottomNumber]];
//[newWardrobe addClothesObject:[delegate.shoesClothesList objectAtIndex:delegate.currentShoeNumber]];
// not sure if this is going to work!
//[newWardrobe addClothesObject:(ClothingItem*) top];
//[newWardrobe addClothesObject:(ClothingItem*) bottom];
//[newWardrobe addClothesObject:(ClothingItem*) shoes];
delegate.numFavorites++; // add another favorite
[[NSUserDefaults standardUserDefaults] setInteger:delegate.numFavorites forKey:@"numFavorites"];
myAlert = [[UIAlertView alloc] initWithTitle: @"Wardrobe Added To Favorites!" message: @"Very nice choice! Awesome style! \n\nReminder: if you select View Favorities you can send this wardrobe to yourself and your friends!" delegate: nil cancelButtonTitle:@"Sweet!" otherButtonTitles:nil];
[myAlert show];
}
以下是我调用getTop,getBottom,getShoes的代码:
// Construct a fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Wardrobe"
inManagedObjectContext:context];
[request setIncludesSubentities:NO];
[request setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:request error:&error];
//ClothingItem *clothingTop, *clothingBottom, *clothingShoes;
NSManagedObject *top = [[fetchedObjects objectAtIndex:currentWardobe] getTop];//[[delegate.favoriteWardrobes objectAtIndex:currentWardobe] objectAtIndex:0];
NSManagedObject *bottom = [[fetchedObjects objectAtIndex:currentWardobe] getBottom];//[[delegate.favoriteWardrobes objectAtIndex:currentWardobe] objectAtIndex:1];
NSManagedObject *shoes = [[fetchedObjects objectAtIndex:currentWardobe] getShoes];//[[delegate.favoriteWardrobes objectAtIndex:currentWardobe] objectAtIndex:2];
关于这里可能出现什么问题的任何想法?