Idan Moshe
Idan Moshe

Reputation: 1533

Core data - data fault

I'm saving data to core data, update, delete etc. I've no error at all regarding core data & saving. But when I try to open the sqlite database file there is nothing there and nothing got updated and saved to core data.

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

Example in updating core data:

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

EDIT: Here is the function that add or update the object:

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

UPDATE - 1: I log the objects and I get this (when I add them to core data):

"<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>)"

And I also log their value and it seems correct value.

Still, its not updated.

Upvotes: 0

Views: 828

Answers (2)

Steve Weller
Steve Weller

Reputation: 4619

Use a recent version of Base or SQLite Professional to examine your database, and you'll be fine.

Upvotes: 0

Marcus S. Zarra
Marcus S. Zarra

Reputation: 46728

How do you know that the data is not in SQLite? Are you looking at the file or are you not seeing the data on screen. Two different potential problems there.

If you are looking in the file and you are on iOS 7 then you are probably looking at journaling being the source of your confusion. Journal mode was turned on in iOS7 and will cause updates to sit in secondary files for a period of time. This would give you the appearance of data not being in the SQLite file because they haven't been moved from the journal files to the SQLite file yet. In this situation, everything is fine.

If you are looking for the data to appear in a view then perhaps your view code is at fault. Posting that view code will help to diagnose it.

I suspect you are looking at the SQLite file though. Correct me if I am wrong.

BTW, this:

[appDelegate.managedObjectContext save:&error];

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

Is a bad way to check for this error. -save: returns a boolean and that should be consulted for an error:

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

Upvotes: 4

Related Questions