ios核心数据未保存

Posted

技术标签:

【中文标题】ios核心数据未保存【英文标题】:Ios core data not saved 【发布时间】:2014-09-11 15:07:36 【问题描述】:

我正在使用核心数据,但我遇到了问题。当我保存数据并且应用程序仍在运行时,我可以查看并获取已保存的数据。

应用程序关闭后,所有字段都将被删除,只保存对象。我可以在 saveContext 方法中看到这一点。 在应用程序关闭时第一次启动时会激活 saveContext 方法。我可以看到 managedObjectContext 对象正在插入新对象。 下次打开应用程序时,managedObjectContext 正在更新对象,所以我知道它保存了对象,但是当我尝试检索它可以找到的对象时。

这是我插入对象的方式:

AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;

    self.managedObjectContext = appDelegate.managedObjectContext;

    @try 
        UserData *userData  =[NSEntityDescription insertNewObjectForEntityForName:[UserTable tableName]                                               inManagedObjectContext:self.managedObjectContext];

        //Insert Values
        userData.facebookId=user.id;
        userData.name=user.name;
        userData.picoAccessToken=[PicoApiManager sharedInstance].accessToken;
        userData.picoExpire=[PicoApiManager sharedInstance].expires;
        userData.latitude=[NSNumber numberWithDouble:user.latitude];
        userData.longitude=[NSNumber numberWithDouble:user.longitude];
        userData.pushId=user.pushId;
        userData.isActive=[NSNumber numberWithBool:activeStatus];
    
    @catch (NSException *exception) 
        NSLog(@"Insert exception - %@", exception.description);
    

  -(void)addPictures:(NSMutableArray *)Pictures;
 
//Setting the isNew field to NO to all the pictures already in the db 
[self updateIsNewOfPicture];
for (Picture *picture in Pictures) 
//Checks if inserted picture is already inside the table

    AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;

    self.managedObjectContext = appDelegate.managedObjectContext;

    @try 
    PictureData *pictureData=[NSEntityDescription insertNewObjectForEntityForName:[PicturesTable     tableName]inManagedObjectContext:self.managedObjectContext];

    //Insert Values
    pictureData.url=picture.source;
    pictureData.isNew=[NSNumber numberWithBool:YES];
    pictureData.isPick=[NSNumber numberWithBool:NO];
    pictureData.timeTaken=picture.time_taken;
    pictureData.albumData=[self getActiveAlbum];
    
    @catch (NSException *exception) 
        NSLog(@"Insert exception - %@", exception.description);
    

这是应用程序委托函数:

     - (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]);
         
    


#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:@"Pico-Db" 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:@"Pico.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) 
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
        

    return _persistentStoreCoordinator;


// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory

    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

这就是我尝试获取数据的方式:

  AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
    //2
    // initializing NSFetchRequest
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    //Setting Entity to be Queried
    NSEntityDescription *entity = [NSEntityDescription entityForName:[UserTable tableName] inManagedObjectContext:appDelegate.managedObjectContext];


    [fetchRequest setEntity:entity];
    NSError* error;

    // Query on managedObjectContext With Generated fetchRequest
    NSArray *fetchedRecords = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    if (fetchedRecords.count >0) 
        return YES;
    

    return NO;

【问题讨论】:

【参考方案1】:

您必须在插入数据后调用-[AppDelegate saveContext],以便CoreData 将更改持久保存到磁盘。 NSManagedObjectContext 会将更改存储在内存中,因此当您的应用程序仍处于活动状态时,您将可以访问数据。但是,一旦应用终止,除非您致电 -[AppDelegate saveContext],否则这些更改将不会保留。

在第一个例子中试试这个:

AppDelegate *appDelegate  = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;

@try 
    UserData *userData = [NSEntityDescription insertNewObjectForEntityForName:[UserTable tableName] inManagedObjectContext:self.managedObjectContext];

    //Insert Values
    userData.facebookId=user.id;
    userData.name=user.name;
    userData.picoAccessToken=[PicoApiManager sharedInstance].accessToken;
    userData.picoExpire=[PicoApiManager sharedInstance].expires;
    userData.latitude=[NSNumber numberWithDouble:user.latitude];
    userData.longitude=[NSNumber numberWithDouble:user.longitude];
    userData.pushId=user.pushId;
    userData.isActive=[NSNumber numberWithBool:activeStatus];

 @catch (NSException *exception) 
    NSLog(@"Insert exception - %@", exception.description);


// SAVE CONTEXT:
[appDelegate saveContext];

在第二个例子中试试这个:

for (Picture *picture in Pictures) 
    // Checks if inserted picture is already inside the table

    AppDelegate* appDelegate  = [UIApplication sharedApplication].delegate;
    self.managedObjectContext = appDelegate.managedObjectContext;

    @try 
        PictureData *pictureData = [NSEntityDescription insertNewObjectForEntityForName:[PicturesTable tableName]inManagedObjectContext:self.managedObjectContext];

        //Insert Values
        pictureData.url=picture.source;
        pictureData.isNew=[NSNumber numberWithBool:YES];
        pictureData.isPick=[NSNumber numberWithBool:NO];
        pictureData.timeTaken=picture.time_taken;
        pictureData.albumData=[self getActiveAlbum];

     @catch (NSException *exception) 
        NSLog(@"Insert exception - %@", exception.description);
    


// SAVE CONTEXT:
[appDelegate saveContext];

创建获取请求:

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"YourEntityName"];
request.sortDescriptors = [NSSortDescriptor sortDescriptorWithKey:@"attributeName" ascending:YES];
request.predicate       = [NSPredicate predicateWithFormat:@"attribute == %@", 13];

NSError *error   = nil; // 
NSArray *results = [appDelegate.managedObjectContext executeFetchRequest:request error:&error];
if (!results) 
    NSLog(@"Error performing fetch request: %@", error.localizedDescription);


return ([results count] > 0); // There are more efficient ways of getting count from CoreData

【讨论】:

在应用程序终止之前,在 applicationWillTerminate 我调用 saveContext 方法。那个电流?或者我每次插入数据时都需要调用这个函数? applicationWillTerminate 不能保证被调用。不应依赖它来保存您的 NSManagedObjectContext。插入数据后或应用程序中的下一个逻辑点应保存上下文。 嘿,对不起,但由于某种原因,它没有帮助。我用来获取信息的代码可以吗? 请看我更新的答案。当您可以将实体名称传递给 NSFetchRequest 初始化程序时,不知道为什么需要麻烦创建 NSEntityDescription

以上是关于ios核心数据未保存的主要内容,如果未能解决你的问题,请参考以下文章

在核心数据swift ios中使用未解析的标识符“模型”

保存已编辑的核心数据实体未保存

未保存到核心数据数据库的对象

核心数据一对多关系未正确/按预期保存

核心数据未保存在分发版本中

核心数据数据未保存