崩溃后核心数据为空

Posted

技术标签:

【中文标题】崩溃后核心数据为空【英文标题】:Core data empty after crash 【发布时间】:2014-11-12 22:57:41 【问题描述】:

我正在模拟崩溃以测试我的应用程序如何响应,并注意到我的core data 在重新启动应用程序时为空。到现在为止,使用核心数据和NSFetchRequest 一直运行良好——我可以终止应用程序或关闭手机,并且数据始终保留。我正在使用核心数据将 URLS 存储到存储在 NSFileManager 中的音​​频文件。当我重新启动应用程序时,我可以看到文件仍在 NSFileManager 中,但 NSFetchRequest 返回的计数为零,而我的 tableview 为空。有没有人经历过这种情况?

编辑:我一直在使用这两行来模拟崩溃:

    NSArray *array = @[];
    array[1];

在我的主视图控制器的viewDidLoad 中,我调用以下代码:

self.managedDocument = [OSManagedDocument getInstance];
[self.managedDocument setUpDocument];  

managedDocument 是一个单例,包含我所有的数据管理方法。

@property (nonatomic, strong) NSManagedObjectContext * managedObjectContext;


+(OSManagedDocument*) getInstance

    static OSManagedDocument* _instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
        _instance = [[OSManagedDocument alloc] init];
    );
    return _instance;


-(void) setUpDocument


    if(self.document == nil)
    
        NSFileManager * fileManager = [NSFileManager defaultManager];
        NSURL * documentsDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
        NSString * documentName = @"MyRecordings";
        self.url = [documentsDirectory URLByAppendingPathComponent:documentName];
        self.document = [[UIManagedDocument alloc] initWithFileURL:self.url];


        BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[self.url path]];

        if(fileExists)
        
             [self.document openWithCompletionHandler:^(BOOL success) 
                if(success)
                
                    [self documentIsReady];

                

             ];
        
        else
        
             [self.document saveToURL:self.url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
                if(success)
                
                     [self documentIsReady];

                
                else
                
                    NSLog(@"Fail");
                

            ];

        
    


-(void) documentIsReady


    if(self.document.documentState ==UIDocumentStateNormal)
    
        self.managedObjectContext = self.document.managedObjectContext;
        NSLog(@"context is ready");
        [self fetchControllerFiles];
        [self recordingCount];
    


-(int) recordingCount


    NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Recording"];
    NSError *error;
    request.predicate = nil;
    request.sortDescriptors =nil;
    NSArray * recordings = [self.managedObjectContext executeFetchRequest:request error:&error];

    NSLog(@"recordings count %lu", (unsigned long)recordings.count);
    return (int)[recordings count];

当我的应用在崩溃后重新启动时,我会调用以下代码:

 -(void) appBecameActive:(NSNotification *)notification
 
     self.managedDocument = [OSManagedDocument getInstance];
 

我调用这个方法来添加核心数据

-(void) saveRecording:(NSMutableDictionary*) recordPackage inManagedObjectContext:(NSManagedObjectContext*) context


    Recording * recording = [NSEntityDescription insertNewObjectForEntityForName:@"Recording" inManagedObjectContext:context];

    recording.trackTitle = [recordPackage objectForKey:@"track label"];
    recording.audioURL = [[recordPackage objectForKey:@"audioURL"] absoluteString];
    recording.timeAdded = [NSDate date];
    recording.waveData = [recordPackage objectForKey:@"waveData"];
    recording.minAmpl = [recordPackage objectForKey:@"minAmpl"];
    recording.recordingNumber = [recordPackage objectForKey:@"recordingNumber"];



【问题讨论】:

[OSManagedDocument getInstance] 是否返回值?还是nilsetUpDocument 方法通过你的if else 语句的路径是什么? OSManagedDocument 没有返回零。对于路径,它识别filesExist为真,success为真,然后调用[self documentIsReady] UIDocumentStateNormal 是真的吗? 是的。输入 IF 语句永远不会有问题。我一直在通过 NSArray *array = @[]; 然后调用 array[1]; 来模拟崩溃 您是否将上下文保存在任何地方?您应该有类似:[context save:&error] 以确保将更新保存回数据库。 【参考方案1】:

我一直依靠自动保存来处理保存,它运行良好,直到我开始强制崩溃以查看应用程序如何恢复。由于每次崩溃后数据都会消失,因此我决定尝试手动保存,并且成功了。现在,即使在强制崩溃之后,数据也会出现。我假设这意味着自动保存没有及时发生。不完全确定如何解释,但手动保存上下文解决了我的问题。

[self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) 
    if(success)
    
        NSLog(@" NEW FILE SAVED");
    
    else
    
        NSLog(@"FAIL TO SAVE");
    

];

【讨论】:

自动保存仅定期发生,而不是在进行更改时自动发生。因此,在您进行更改和自动保存之间有一段时间。如果您在此期间崩溃,您的数据将会丢失。您的手动保存可避免此问题。

以上是关于崩溃后核心数据为空的主要内容,如果未能解决你的问题,请参考以下文章

迁移后更改核心数据时崩溃

删除后尝试保存时核心数据崩溃

向实体添加属性后快速核心数据崩溃

核心数据 - 向 xcddatamodel 文件添加额外属性后应用程序崩溃

轻量级核心数据迁移后崩溃

xcode ios:将核心数据包含到旧项目后崩溃