2011-10-04 39 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知道它們已更改,從而存儲它們。