2011-10-04 28 views
2

我有一个相当简单的iPhone应用程序,它利用CoreData来实现对象持久性 该对象除了其他属性之外还有一个NSNumber属性,在数据模型中定义其他属性,我在应用程序运行周期中将其设置为1,如果用户点击某个特定的按钮,然后调用肯定会调用的存储函数,并且与持久化其他所有函数一样,并且这似乎工作暂时的,因为如果我检查我的NSManagedObject属性的值,它具有正确的值,如果我从数据存储检索对象并检查它仍然有正确的值。但是,如果我重新启动应用程序,它没有坚持,所以它恢复到默认状态。我变得非常沮丧,并尝试了各种方法强制ManagedObjectContext坚持下去。NSManagedObject不会被持久化 - 无论我多么努力地尝试:(

相关代码: 持久性代码...

- (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

// 
// 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

// 
// 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 

回答

4

你有@synthesize d您的访问器是什么想必管理对象属性。这意味着它们不会通过正确的核心数据访问器,也不会正确更新模型。应该使用@dynamic来告诉编译器正确的访问器将在运行时可用(核心数据框架将提供它们)。

我认为你现在拥有的东西基本上使你的所有属性都是瞬态的。

+0

引起了一大堆问题的解决,但现在它工作得很好 - 非常感谢。 –

3

您应该使所有属性@dynamic@synthesize将为每个属性创建一个getter和setter,但对CoreData存储系统不做任何事情。 也就是说,更改这些值不会导致CoreData知道它们已更改,从而存储它们。