我有一个相当简单的iPhone应用程序,它利用CoreData进行对象持久化。
除其他属性外,该对象还具有在数据模型中定义的NSNumber属性以及所有其他属性。如果用户单击特定按钮,则在应用程序运行周期中将其设置为1。然后,我调用存储函数,该函数肯定会被调用,并且与其他所有持久化函数相同,并且这似乎是暂时起作用的,因为如果我在NSManagedObject上检查属性的值,则它具有正确的值,如果我从数据存储中检索对象,并检查它是否仍然具有正确的值。但是,如果我重新启动该应用程序,则该应用程序不会持续存在,因此将恢复为默认状态。我感到非常沮丧,并尝试了各种强制ManagedObjectContext持久化的方法。
相关代码:
持续性代码...
- (Area*) storeAreaFavourite:(Area*)a
{
a = [self storeArea:a];
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
//[context refreshObject:a mergeChanges:YES];
[context processPendingChanges];
NSLog(@"Stored area with favourite: %@",([a favourite] != nil ? [a favourite] : [NSNumber numberWithInt: 0]));
return a;
}
- (Area*) storeArea:(Area*)a
{
NSError *error = nil;
// Create a new instance of the entity managed by the fetched results controller.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSFetchRequest* request = [[NSFetchRequest alloc] init];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Area" inManagedObjectContext:context];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"areaId=%@", [a areaId]];
[request setEntity:entity];
[request setPredicate:predicate];
NSArray* matchedAreas = [context executeFetchRequest:request error:&error];
if (error != nil)
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
//NSLog(@"Matched %d Areas", [matchedAreas count]);
Area* newArea = [matchedAreas count] > 0 ? [matchedAreas objectAtIndex:0] : nil;
if (newArea == nil)
{
newArea = [NSEntityDescription insertNewObjectForEntityForName:@"Area" inManagedObjectContext:context];
}
else {
//NSLog(@"Area: %@ -> %@ ParentArea: %@ -> %@", [newArea valueForKey:@"areaId"], [a areaId], [(Area*)[newArea valueForKey:@"parentArea"] areaId], [(Area*)[a parentArea] areaId]);
}
// If appropriate, configure the new managed object.
[newArea setValue:[a areaId] forKey:@"areaId"];
[newArea setValue:[a areaName] forKey:@"areaName"];
[newArea setValue:[a parentArea] forKey:@"parentArea"];
[newArea setValue:[a height] forKey:@"height"];
[newArea setValue:[a width] forKey:@"width"];
[newArea setValue:[a xPos] forKey:@"xPos"];
[newArea setValue:[a yPos] forKey:@"yPos"];
[newArea setValue:[a childAreas] forKey:@"childAreas"];
[newArea setValue:[a imageName] forKey:@"imageName"];
[newArea setValue:[a areaText] forKey:@"areaText"];
[newArea setValue:([a favourite] != nil ? [a favourite] : [NSNumber numberWithInt: 0]) forKey:@"favourite"];
if ([a favourite] != nil && [[NSNumber numberWithInt:1] isEqualToNumber:[a favourite]])
{
NSLog(@"Storing area with areaId: %@",[a areaId]);
NSLog(@"Storing area with areaName: %@",[a areaName]);
NSLog(@"Storing area with parentArea: %@",[a parentArea]);
NSLog(@"Storing area with height: %@",[a height]);
NSLog(@"Storing area with width: %@",[a width]);
NSLog(@"Storing area with xPos: %@",[a xPos]);
NSLog(@"Storing area with yPos: %@",[a yPos]);
NSLog(@"Storing area with childAreas: %@",[a childAreas]);
NSLog(@"Storing area with imageName: %@",[a imageName]);
NSLog(@"Storing area with areaText: %@",[a areaText]);
NSLog(@"Storing area with favourite: %@",([a favourite] != nil ? [a favourite] : [NSNumber numberWithInt: 0]));
}
// Save the context.
if (![context save:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
//abort();
}
matchedAreas = [context executeFetchRequest:request error:&error];
if (error != nil)
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
//NSLog(@"Matched %d Areas", [matchedAreas count]);
newArea = [matchedAreas count] > 0 ? [matchedAreas objectAtIndex:0] : nil;
if (newArea != nil)
{
NSLog(@"StoredFav:%@:%@",[newArea areaId],[newArea favourite]);
}
return newArea;
}
是上午
//
// Area.m
// MappApp
//
// Created by Matthew Fellows on 27/07/2011.
//
#import "Area.h"
@implementation Area
@synthesize height;
@synthesize areaId;
@synthesize xPos;
@synthesize areaName;
@synthesize width;
@synthesize areaText;
@synthesize imageName;
@synthesize yPos;
@synthesize childAreas;
@synthesize parentArea;
@synthesize areaImages;
@synthesize favourite;
- (void)addChildAreasObject:(NSManagedObject *)value{
if (childAreas == nil)
{
childAreas = [[NSMutableSet alloc] init];
}
[childAreas addObject:value];
}
- (void)addAreaImagesObject:(NSManagedObject *)value{
if (areaImages == nil)
{
areaImages = [[NSMutableSet alloc] init];
}
[areaImages addObject:value];
}
@end
面积
//
// Area.h
// MappApp
//
// Created by Matthew Fellows on 27/07/2011.
//
#import <CoreData/CoreData.h>
@interface Area : NSManagedObject
{
NSMutableSet* areaImages;
NSMutableSet* childAreas;
}
@property (nonatomic, retain) NSNumber * height;
@property (nonatomic, retain) NSNumber * areaId;
@property (nonatomic, retain) NSNumber * xPos;
@property (nonatomic, retain) NSString * areaName;
@property (nonatomic, retain) NSNumber * width;
@property (nonatomic, retain) NSString * areaText;
@property (nonatomic, retain) NSString * imageName;
@property (nonatomic, retain) NSNumber * yPos;
@property (nonatomic, retain) NSMutableSet* childAreas;
@property (nonatomic, retain) NSManagedObject * parentArea;
@property (nonatomic, retain) NSMutableSet* areaImages;
@property (nonatomic, retain) NSNumber* favourite;
@end
@interface Area (CoreDataGeneratedAccessors)
- (void)addChildAreasObject:(NSManagedObject *)value;
- (void)removeChildAreasObject:(NSManagedObject *)value;
- (void)addChildAreas:(NSSet *)value;
- (void)removeChildAreas:(NSSet *)value;
- (void)addAreaImagesObject:(NSManagedObject *)value;
- (void)removeAreaImagesObject:(NSManagedObject *)value;
- (void)addAreaImages:(NSSet *)value;
- (void)removeAreaImages:(NSSet *)value;
@end
最佳答案
您已经为可能是托管对象属性的访问器@synthesize
d了。这意味着它们将无法通过正确的核心数据访问器,也不会正确更新模型。 @dynamic
应该用于告诉编译器在运行时将提供适当的访问器(核心数据框架将提供它们)。
我认为现在您拥有的东西基本上已经使您的所有属性成为瞬时的。