2012-09-19 129 views
6

Guy希望你會好起來的。當我重新啓動應用程序(核心數據)時丟失了數據

我是iPhone開發新手。我正在用核心數據創建一個簡單的應用程序。在應用程序中,當我保存數據時,它工作正常,然後我檢索數據,它也工作正常。但是當我重新啓動應用程序時,所有的數據都會丟失。

On啓動應用程序時,在ViewDidLoad函數中,我正在使用在工作應用程序中檢索的相同函數檢索數據。

保存數據的方法:

NSManagedObjectContext *context=[app managedObjectContext]; 
    Contacts *data=[NSEntityDescription insertNewObjectForEntityForName:@"Contacts" inManagedObjectContext:context]; 
    if(nameField.text.length <=0 || phoneField.text.length <=0) 
    { 

     UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Warning!" message:@"Please enter some data." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; 
     [alert show]; 
    } 
    else 
    { 
     data.name = nameField.text; 
     data.phone = phoneField.text; 
     NSLog(data.name); 
     NSLog(data.phone); 
     [self.navigationController popToRootViewControllerAnimated:YES]; 

    } 

檢索數據的方法:

NSEntityDescription *entity=[NSEntityDescription entityForName:@"Database" inManagedObjectContext:context]; 

    NSFetchRequest *fetchRequest=[[NSFetchRequest alloc]init]; 

    [fetchRequest setFetchBatchSize:20]; 

    [fetchRequest setEntity:entity]; 

    NSSortDescriptor *sorting = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 

    NSArray *sorted_Array=[NSArray arrayWithObject:sorting]; 

    [fetchRequest setSortDescriptors:sorted_Array]; 

    NSError *error; 

    NSMutableArray *tArray=[[context executeFetchRequest:fetchRequest error:&error]mutableCopy]; 

    [self setArray:tArray]; 
    [self.tableView reloadData]; 

應用代表代碼

#import "ZAppDelegate.h" 
#import "Contacts.h" 

@implementation ZAppDelegate 

@synthesize window = _window; 
@synthesize managedObjectContext = __managedObjectContext; 
@synthesize managedObjectModel = __managedObjectModel; 
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator; 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    // Override point for customization after application launch. 

    TableViewController *TVC=[[TableViewController alloc]init]; 

    TVC.MOcontext=self.managedObjectContext; 

    UINavigationController *nvgc=[[UINavigationController alloc]initWithRootViewController:TVC]; 
    self.window.rootViewController=nvgc; 


    self.window.backgroundColor = [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

- (void)applicationWillResignActive:(UIApplication *)application 
{ 
    /* 
    Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
    Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
    */ 
} 

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    /* 
    Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
    */ 
} 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 
    /* 
    Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 
    */ 
} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    /* 
    Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
    */ 
} 

- (void)applicationWillTerminate:(UIApplication *)application 
{ 
    // Saves changes in the application's managed object context before the application terminates. 
    [self saveContext]; 
} 

- (void)saveContext 
{ 
    NSError *error = nil; 
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 
    if (managedObjectContext != nil) 
    { 
     if ([managedObjectContext hasChanges] && ![managedObjectContext 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. 
      */ 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
    } 
} 

#pragma mark - Core Data stack 

/** 
Returns the managed object context for the application. 
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application. 
*/ 
- (NSManagedObjectContext *)managedObjectContext 
{ 
    if (__managedObjectContext != nil) 
    { 
     return __managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) 
    { 
     __managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [__managedObjectContext setPersistentStoreCoordinator:coordinator]; 
    } 
    return __managedObjectContext; 
} 

/** 
Returns the managed object model for the application. 
If the model doesn't already exist, it is created from the application's model. 
*/ 
- (NSManagedObjectModel *)managedObjectModel 
{ 
    if (__managedObjectModel != nil) 
    { 
     return __managedObjectModel; 
    } 
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Diary" withExtension:@"momd"]; 
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
    return __managedObjectModel; 
} 

/** 
Returns the persistent store coordinator for the application. 
If the coordinator doesn't already exist, it is created and the application's store added to it. 
*/ 
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
    if (__persistentStoreCoordinator != nil) 
    { 
     return __persistentStoreCoordinator; 
    } 

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Diary.sqlite"]; 

    NSError *error = nil; 
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&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. 

     Typical reasons for an error here include: 
     * The persistent store is not accessible; 
     * The schema for the persistent store is incompatible with current managed object model. 
     Check the error message to determine what the actual problem was. 


     If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory. 

     If you encounter schema incompatibility errors during development, you can reduce their frequency by: 
     * Simply deleting the existing store: 
     [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil] 

     * Performing automatic lightweight migration by passing the following dictionary as the options parameter: 
     [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 

     Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details. 

     */ 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    }  

    return __persistentStoreCoordinator; 
} 

#pragma mark - Application's Documents directory 

/** 
Returns the URL to the application's Documents directory. 
*/ 
- (NSURL *)applicationDocumentsDirectory 
{ 
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
} 

@end 

這裏有什麼不對嗎? 我希望能儘早得到好答案。

+1

在您發佈的代碼中,您永遠不會發送'NSManagedObjectContext'保存'消息。直到您這樣做,您的更改纔會持續到'NSPersistentStore'。 – FluffulousChimp

+0

@alanduncan:感謝您的回覆。我可否知道如何在NSPersistentStore中保留更改? – iOmi

+0

Dude,同樣的事情發生在我身上,但使用Visual Studio 2012和EntityFramework在VB.NET和DB = SQL Server 2012 Express中運行控制檯應用程序。數據保存,使用.SaveChanges(我運行在每個循環結束,其中每個循環寫入另一行)。現在,當我以調試模式關閉應用程序時,數據仍然存在。沒有任何問題。但是,當我通過IDE以調試模式重新啓動應用程序時,所有在上次應用程序中運行的數據(在上次執行期間保存的數據)都將被刪除並不再存在。快把我逼瘋。你能解決嗎?任何人閱讀這可以幫助嗎? –

回答

6

在某個時間點應用程序的生命週期中,您需要撥打saveNSManagedObjectContext或您的更改不會持續到NSPersistentStore。例如在應用程序代理的applicationDidEnterBackground:方法中。

NSError *saveError = nil; 
if(![[self managedObjectContext] save:&saveError]) { 
    // deal with error... 
} 

我假設你的應用程序委託建立和維護核心數據堆棧像蘋果模板做...

+0

@aladuncan ::我在應用程序生命週期中的按鈕動作上調用** save **。它不好嗎? – iOmi

+0

儘管使用此按鈕操作保存了「NSManagedObject」上下文,否則您的數據沒有被保存?通常,當您的應用程序進入後臺時,您還需要保存上下文。否則,當用戶點擊主頁按鈕時會發生什麼,然後你的應用程序就會被殺死?你是否檢查'save'方法的結果以確保沒有錯誤? – FluffulousChimp

+0

@aladuncan ::是!我檢查了** save **方法,放置了斷點,逐行調試它。它工作正常。每當我的應用程序啓動** Retreive **方法被調用,但它什麼也沒有發出。我無法檢查數據是否正在保存(保持)或不在數據文件中的數據。 我假設,就像.NET一樣,當我們使用SQL-Server並創建數據庫時,它會創建一個SQL-Server數據庫文件,計算該文件的大小,我可以檢查該數據是否不保存。 所以在iOS中,有沒有像.NET一樣的東西? – iOmi

0

我沒有看到你把代碼保存。你需要告訴managedcontext保存。你做什麼取決於你的應用和設計。如果你認爲它已經在你的應用程序的某個地方,那麼添加一些NSLog來嘗試和調試,或者使用調試器工具來實際進入你的代碼。

這是一個簡單的修復。祝你好運。

+0

我使用** NSLog **和調試器工具。應用程序在運行時工作正常,它保存數據,檢索數據,但是當我重新啓動它時,所有數據都消失了。 – iOmi

+1

NSPersistant商店中的更改通常位於應用程序delegate.m中並且當您保存到上述其他人的上下文中時,它將與app delegate.m文件一起使用以保存;您介意在app app delegate.m文件中顯示代碼以及您明確保存的位置嗎?我很樂意提供幫助,但我需要查看這兩部分的代碼。使用NSLog的好工作..這是一個很好的方式來調試以及使用調試器。保持! – holster

+0

::感謝您的回答,我真的很抱歉爲您播放遲到。我用** appDelegate.m **代碼更新了我的問題。請看** appDelegate.m **部分。 而我明確保存的部分是**保存數據方法**,我已經在頂部的問題中提到過了。 – iOmi

4

在你的AppDelegate:

- (void)applicationWillTerminate:(UIApplication *)application 
{ 
    // Saves changes in the application's managed object context before the application terminates. 
    [self saveContext]; 
} 

-saveContext可能在Xcode的模板的早期版本-save


而且更重要的是,你可以調用其他類-save-saveContent方法:

[(AppDelegate *)[UIApplication sharedApplication] saveContext]; 
0

的NSManagedObjectContext中提供了一個便籤:無論你與你的目標和你一樣可以做,但需要在最後保存它。直到您保存它,對NSManagedObjectContext所做的任何更改都是臨時的。嘗試添加給你的方法結束:

if (![context save:&error]) { 
NSLog(@"Couldn't save: %@", error); 
} 
0

此背景下需要保存
CoreDataManager *上下文= [CoreDataManager sharedInstance]
...
..
...
...
.....
...
[上下文saveContext];

相關問題