Сохраненные основные данные не сохраняются после закрытия приложения в 80% случаев - PullRequest
1 голос
/ 08 марта 2012

Я начал работать с Core Data в последнее время, и в своих тестах я обнаружил, что примерно 20% времени данные фактически сохраняются в БД. В остальное время он сохраняется только временно, пока приложение работает. При перезапуске последние сохраненные данные теряются.

Кто-нибудь знает, в чем может быть проблема?

Вот код:

//Save data
NSEntityDescription *users = [NSEntityDescription insertNewObjectForEntityForName:@"Users" inManagedObjectContext:document.managedObjectContext];
[users setValue:@"Name Test" forKey:@"name"];
[users setValue:[NSNumber numberWithInt:20] forKey:@"age"];
[users setValue:@"Some Country" forKey:@"location"];


//Debugging
//no error ever shows up
NSError *error;
if(![document.managedObjectContext save:&error]) {
    NSLog(@"Error: %@", error);
}

//this is just to show that the problem may not be with my UIManagedDocument (self.document), since the NSLog never gets called.
if(self.document.documentState != UIDocumentStateNormal) {
    NSLog(@"Document is not opened");
}
//End of debugging


//Fetch all the data from the entity
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Users"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
fetch.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

NSArray *results = [document.managedObjectContext executeFetchRequest:fetch error:nil];
NSLog(@"Results on the database: %d", [results count]);

document - это то же самое (по крайней мере, я на это надеюсь, в большинстве случаев) как self.document; это просто аргумент метода, в котором расположен этот код.

Вот код для моих .h и .m:

.h:

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@interface CoreDataViewController : UIViewController

@property (nonatomic, strong) UIManagedDocument *document;

@end

.m:

#import "CoreDataViewController.h"

@implementation CoreDataViewController
@synthesize document = _document;

- (void)fetchStuff:(UIManagedDocument *)document {

    //Save data
    NSEntityDescription *users = [NSEntityDescription insertNewObjectForEntityForName:@"Users" inManagedObjectContext:document.managedObjectContext];
    [users setValue:@"Name Test" forKey:@"name"];
    [users setValue:[NSNumber numberWithInt:20] forKey:@"age"];
    [users setValue:@"Some Country" forKey:@"location"];


    //Debugging
    //no error ever shows up
    NSError *error;
    if(![document.managedObjectContext save:&error]) {
        NSLog(@"Error: %@", error);
    }

    //this is just to show that the problem may not be with my UIManagedDocument (self.document), since the NSLog never gets called.
    if(document.documentState != UIDocumentStateNormal) {
        NSLog(@"Document is not opened");
    }
    //End of debugging


    //Fetch all the data from the entity
    NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Users"];
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    fetch.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

    NSArray *results = [document.managedObjectContext executeFetchRequest:fetch error:nil];
    NSLog(@"Results on the database: %d", [results count]);
}

- (void)useDocument {
    if(![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]) {
        [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){
            if(success == YES) NSLog(@"created");
            [self fetchStuff:self.document];
        }];
    } else if(self.document.documentState == UIDocumentStateClosed) {
        [self.document openWithCompletionHandler:^(BOOL success) {
            if(success == YES) NSLog(@"opened");
            [self fetchStuff:self.document];
        }];
    } else if(self.document.documentState == UIDocumentStateNormal) {
        [self fetchStuff:self.document];
    }
}

- (void)setDocument:(UIManagedDocument *)document {
    if(_document != document) {
        _document = document;
        [self useDocument];
    }
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if(!self.document) {
        NSURL *url = [[[NSFileManager defaultManager]URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        url = [url URLByAppendingPathComponent:@"Database"];
        self.document = [[UIManagedDocument alloc]initWithFileURL:url];
    }
}

@end

Примечание: есть также моя модель данных, в которой есть сущность "Пользователи" с атрибутами age, location, name.

Ответы [ 3 ]

6 голосов
/ 08 марта 2012

Данные сохранялись иногда из-за автосохранения, которое происходит каждые X (может быть, 10, мне нужно проверить документацию) секунд. Чтобы заставить сохранить, я должен был использовать это:

[documentation saveToURL:documentation.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
if(success == YES) NSLog(@"Awesome, it's saved!");
}];

Хотя это нормально работает при добавлении этого кода в fetchStuff:, было бы лучше реализовать это, когда пользователь выходит из экрана, поскольку он может быть автоматически сохранен с помощью автосохранения.

2 голосов
/ 18 апреля 2012

Вы не должны вызывать save на UIManagedDocument MOC. Вот отредактированная версия вашего кода. Пожалуйста, попробуйте.

//Save data
NSEntityDescription *users = [NSEntityDescription insertNewObjectForEntityForName:@"Users" inManagedObjectContext:document.managedObjectContext];
[users setValue:@"Name Test" forKey:@"name"];
[users setValue:[NSNumber numberWithInt:20] forKey:@"age"];
[users setValue:@"Some Country" forKey:@"location"];

// Removed save on UIMDMOC - We let auto-save do the work
// However, we have to tell the document that it needs to 
// be saved. Now, the changes in the "main" MOC will get pushed
// to the "parent" MOC, and when appropriate, will get save to disk.
[document updateChangeCount:UIDocumentChangeDone];

if(self.document.documentState != UIDocumentStateNormal) {
    NSLog(@"Document is not opened");
}    

//Fetch all the data from the entity
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Users"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
fetch.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

NSArray *results = [document.managedObjectContext executeFetchRequest:fetch error:nil];
NSLog(@"Results on the database: %d", [results count]);

ОК ... Это было не слишком больно ... просто удалил вызов для сохранения и заменил его вызовом, который сообщает UIManagedDocument, что некоторые изменения были внесены, и их необходимо сохранить.

0 голосов
/ 19 апреля 2014
    Record *newentry = [NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:self.mManagedObjectContext];
    newentry.code = entryStr;
    NSError *error;
    if ([self.mManagedObjectContext save:&error])
    {
        NSLog(@"save successfully");
    }
    else
    {
        NSLog(@"fail to save");
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...