核心数据——数据故障

Posted

技术标签:

【中文标题】核心数据——数据故障【英文标题】:Core data - data fault 【发布时间】:2014-02-09 13:35:02 【问题描述】:

我正在将数据保存到核心数据、更新、删除等。 关于核心数据和保存,我完全没有错误。 但是当我尝试打开 sqlite 数据库文件时,那里什么都没有,也没有任何更新和保存到核心数据。

AppDelegate:

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


// 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:@"CoreDataModel" 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:@"CoreDataModel.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;


#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];

更新核心数据示例:

- (void)enableORdisableAlertInDatabase:(FMDatabase*)database andOperation:(int)operation andTrapID:(int)trapID

    NSLog(@"%s", __PRETTY_FUNCTION__);

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_TRAP_ENTITY inManagedObjectContext:appDelegate.managedObjectContext];
    [fetchRequest setEntity:entity];
    // Specify criteria for filtering which objects to fetch
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"trapID==%i", trapID];
    [fetchRequest setPredicate:predicate];

    NSError *error = nil;
    NSArray *fetchedObjects = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    if (fetchedObjects == nil) 
        NSLog(@"%s error: %@", __PRETTY_FUNCTION__, error.localizedDescription);
    
    else 
        CoreDataTrap *trap = (CoreDataTrap*)fetchedObjects.firstObject;
        [trap setAlert:[NSNumber numberWithInt:operation]];

        [appDelegate.managedObjectContext save:&error];

        if (error != nil) 
            NSLog(@"enableORdisableAlertInDatabase Error: %@", error.localizedDescription);
        
    

编辑: 这是添加或更新对象的函数:

- (void)addOrUpdateTrap:(Traps*)trapObject

    int trapID = trapObject.getTrapID;
    CoreDataTrap *trapEntity = nil;
    NSError *error = nil;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"CoreDataTrap"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"trapID == %d", trapID];
    [fetchRequest setPredicate:predicate];

    NSArray *results = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    if (results == nil)
    
        // Handle error
    
    else if ([results count] == 0)
    
        // Nothing to update, add new trap
        // Create a new record (row)
        trapEntity = [NSEntityDescription insertNewObjectForEntityForName:@"CoreDataTrap" inManagedObjectContext:appDelegate.managedObjectContext];
    
    else
    
        trapEntity = results[0]; // There should be only one object for the ID.
    


    if (trapEntity != nil)
    
        // Set properties for new or existing object ...

        // Int
        [trapEntity setTrapID:[NSNumber numberWithInt:trapObject.getTrapID]];
        [trapEntity setType:[NSNumber numberWithInt:trapObject.getTrapType]];
        [trapEntity setDist:[NSNumber numberWithInt:trapObject.getTrapDistanceToCar]];
        [trapEntity setDist_to_close_point:[NSNumber numberWithInt:trapObject.getTrapDistanceToClosePoint]];
        [trapEntity setActive:[NSNumber numberWithInt:trapObject.isActive]];
        [trapEntity setAlert:[NSNumber numberWithInt:trapObject.isAlert]];
        [trapEntity setAlarmDistance:[NSNumber numberWithInt:trapObject.alarmDistance]];
        [trapEntity setRoadNumber:[NSNumber numberWithInt:trapObject.roadNumber]];
        [trapEntity setPolys:[NSNumber numberWithInt:trapObject.polygons]];
        [trapEntity setEnter_to_area:[NSNumber numberWithInt:trapObject.getTrapEnterToArea]];

        // Double
        [trapEntity setLat:[NSNumber numberWithDouble:trapObject.getTrapLat]];
        [trapEntity setLon:[NSNumber numberWithDouble:trapObject.getTrapLon]];
        [trapEntity setClose_point_lat:[NSNumber numberWithDouble:trapObject.getTrapClosePointLat]];
        [trapEntity setClose_point_lon:[NSNumber numberWithDouble:trapObject.getTrapClosePointLon]];

        // NSString
        [trapEntity setLastTrapAlarm:[NSString stringWithFormat:@"%li", trapObject.getTrapLastAlarm]];
        [trapEntity setPoly0:trapObject.getTrapPolygonA];
        [trapEntity setPoly1: trapObject.getTrapPolygonB];
        [trapEntity setPoly2: trapObject.getTrapPolygonC];
        [trapEntity setPolygonAzimut1: trapObject.getTrapPolygonAzimuthA];
        [trapEntity setPolygonAzimut2: trapObject.getTrapPolygonAzimuthB];
        [trapEntity setPolygonAzimut3: trapObject.getTrapPolygonAzimuthC];
        [trapEntity setDesc: trapObject.getTrapDesc];
        // etc. for all properties ...

        error = nil;
        if (![appDelegate.managedObjectContext save:&error])
        
            NSLog(@"%s error: %@", __PRETTY_FUNCTION__, error.localizedDescription);
        
    

更新 - 1: 我记录了对象并得到了这个(当我将它们添加到核心数据时):

"<CoreDataTrap: 0x147c4140> (entity: CoreDataTrap; id: 0x1477d510 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p11> ; data: <fault>)",
    "<CoreDataTrap: 0x147c4240> (entity: CoreDataTrap; id: 0x1477d520 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p12> ; data: <fault>)",
    "<CoreDataTrap: 0x145507d0> (entity: CoreDataTrap; id: 0x147cd410 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p13> ; data: <fault>)",
    "<CoreDataTrap: 0x14550900> (entity: CoreDataTrap; id: 0x147cd420 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p14> ; data: <fault>)",
    "<CoreDataTrap: 0x14550a30> (entity: CoreDataTrap; id: 0x147cd430 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p15> ; data: <fault>)",
    "<CoreDataTrap: 0x145401b0> (entity: CoreDataTrap; id: 0x147cd440 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p16> ; data: <fault>)",
    "<CoreDataTrap: 0x145402b0> (entity: CoreDataTrap; id: 0x147cd450 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p17> ; data: <fault>)",
    "<CoreDataTrap: 0x14540440> (entity: CoreDataTrap; id: 0x147cd460 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p18> ; data: <fault>)",
    "<CoreDataTrap: 0x1453e380> (entity: CoreDataTrap; id: 0x147cd470 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p19> ; data: <fault>)",
    "<CoreDataTrap: 0x1453e480> (entity: CoreDataTrap; id: 0x147cd480 <x-coredata://CD85E666-FA17-4D5F-A221-9BC962C7667B/CoreDataTrap/p20> ; data: <fault>)"

我还记录了它们的值,这似乎是正确的值。

仍然没有更新。

【问题讨论】:

您确定您曾经将对象插入到对象图中吗?如果是这样,请在您创建对象的位置发布代码。您正在尝试保存之前检查上下文是否有任何更改,因此如果没有更改(因此不会显示错误),则不会执行保存。 我在第一次添加代码时添加了它。 【参考方案1】:

你怎么知道数据不在 SQLite 中?您是在查看文件还是在屏幕上看不到数据。有两个不同的潜在问题。

如果您正在查看文件并且您使用的是 ios 7,那么您可能会认为日记是您困惑的根源。日记模式在 iOS7 中打开,会导致更新在辅助文件中保留一段时间。这将使您看起来数据不在 SQLite 文件中,因为它们尚未从日志文件移动到 SQLite 文件。在这种情况下,一切都很好。

如果您正在寻找要出现在视图中的数据,那么您的视图代码可能有问题。发布该视图代码将有助于诊断它。

我怀疑您正在查看 SQLite 文件。如果我错了,请纠正我。

顺便说一句,这个:

[appDelegate.managedObjectContext save:&error];

if (error != nil) 
  NSLog(@"enableORdisableAlertInDatabase Error: %@", error.localizedDescription);

检查此错误是一种不好的方法。 -save: 返回一个布尔值,如果出现错误,请查阅该值:

if ([[appDelegate managedObjectContext] save:&error] == NO) 
  NSLog(@"Error saving: %@\n%@", [error localizedDescription], [error userInfo]);

【讨论】:

好的,如何查看 sqlite 文件?我的代码有效,没有错误,但我仍然想检查 sqlite 文件。 当它有更多数据时,你可以举例。日志文件最终将被消耗到 SQLite 文件中。另一种选择是清理 SQLite 文件,这将强制它使用这些文件。 如何清理 SQLite 文件?当我提取保存在手机上的应用程序的所有文件时,我确实有 SQLite 文件,但有关核心数据的文件是空的,有什么想法吗? 同样,它们是空的,因为数据在日志文件中。如果你用谷歌搜索“vacuum SQLite”,你会发现在命令行上打开文件(使用 sqlite CLI 应用程序)并输入VACUUM 将导致数据库被重建,日志文件被消耗,你会看到你的数据.或者您可以只查看应用程序中的数据,并将实现细节留给 Core Data。【参考方案2】:

使用最新版本的 Base 或 SQLite Professional 检查您的数据库,一切都会好起来的。

【讨论】:

a)这只是一个意见 - 还有其他应用程序可以读取 SQLite 文件 b)更重要的是,问题的原因是日志记录,而不是无法读取文件。

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

核心数据故障消息

iOS 中的核心数据故障

由于核心数据故障,应用程序在启动时崩溃

在swift ios中再次运行应用程序后核心数据显示故障记录?

在获取永久 ID 后,核心数据无法为对象完成故障

与故障相关的很少核心数据崩溃