Search code examples
ioscore-dataattributesnsmutabledictionarytransformable

How to update transformable attribute in core data


I am in a situation where i need to update transformable attribute in my entity in core data, until now i've tried every possible answer from google and stack overflow but did't achieve anything.

This is the method where i am saving object in core data, and my object which i am saving is an NSMutablDictionary type object.

-(void)didSaveToCoreData :(NSMutableDictionary *)newDict
{

@try {
    AppDelegate *appDelegate  = [[UIApplication sharedApplication]delegate];

    NSManagedObjectContext *context = appDelegate.managedObjectContext ;

    DataModelSupport *entity = [NSEntityDescription insertNewObjectForEntityForName:@"CPIEntity" inManagedObjectContext:context];


    if (newDict != nil) {

        [entity.fixed_Model removeAllObjects];
        entity.fixed_Model = newDict;
    }

    NSError *error ;
    [context save:&error];
    if(error)
    {
        NSLog(@"Error in Saving Data");
    }
    else
    {
        [self didFetchFromCoreDataModel];
        NSLog(@"Successfully saved");
    }

}
@catch (NSException *exception) {
    [self spareMeFromTheCrash:exception];
}
@finally {

}

}

in this method i am saving a dictionary object of 19 key/value, at the first time and i am fetching it correctly in didFetchFromCoreDataModel method, but when i refresh the data and get dictionary of 18 key/value i save that dictionary in core data using the same method didSaveToCoreData and fetch it in the same way from didFetchFromCoreDataModel but it still show 19 key/value

DataModelSupport is a subclass of NSManagedObject. In DataModelSupport.h:

@property (nonatomic,weak) NSMutableDictionary *fixed_Model;

In DataModelSupport.m:

@dynamic fixed_Model;

This is it for the DataModelSupport class.

Now here in this method i am fetching the same object form core data

-(void)didFetchFromCoreDataModel
{

@try {
    AppDelegate *appDelegate  = [[UIApplication sharedApplication]delegate];

    NSManagedObjectContext *context = appDelegate.managedObjectContext ;
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"CPIEntity" inManagedObjectContext:context];

    NSFetchRequest *request = [[NSFetchRequest alloc]init];
    [request setReturnsDistinctResults:YES];
    [request setReturnsObjectsAsFaults:NO];
    [request setResultType:NSDictionaryResultType];
    [request setEntity:entity];
    NSError *error ;

    NSArray *arr = [context executeFetchRequest:request error:&error];

    updatedfinalArr = [arr valueForKey:@"fixed_Model"];



    if(error)
    {
        NSLog(@"Error");
    }
    else
    {

    }

}
@catch (NSException *exception) {
    [self spareMeFromTheCrash:exception];
}
@finally {

}

}

And this is how my core data looks like:- enter image description here

Any help is appreciated.

EDIT

I've implemented some changes in my code now in didSaveToCoreData method i am using this line of code to fetch the Entity by name

NSEntityDescription *descriptor = [NSEntityDescription entityForName:@"CPIEntity" inManagedObjectContext:context];

by this i am not creating new entity every time i call didSaveToCoreData method.

and this is how i am saving NSMutlableDictionary object

DataModelSupport *entity = [[DataModelSupport alloc]initWithEntity:descriptor insertIntoManagedObjectContext:context];
[entity.fixed_Model removeAllObjects]
entity.fixed_Model = newDict;

but still i am not getting correct result. now when i refresh the data and save it using the above procedure explained in EDIT section, and fetch it, i get the updated data but it increase the number of objects, like on first attempt when i fetch i got 1 object in array, and on second attempt i got 2 objects and it goes like this, so when ever new data is added its not updating it but instead it add it in the entity s fixed_Model attribute and increase the number of object.

Lastly now i am using this line of code to get the last and update object from array in didFetchFromCoreDataModel method

NSDictionary *ddd = [[arr valueForKey:@"fixed_Model"]lastObject];
updatedfinalArr = [NSMutableArray arrayWithObject:ddd];

Solution

  • Your save method creates a new CPIEntity object each time. So, unless you delete the old object elsewhere in your code, I suspect your fetch is returning several objects, the first of which has the dictionary with 19 key/value pairs in the fixed_Model attribute, and the second/subsequent objects contain the 18 key/value pairs.

    When you save, you should try to fetch the existing object first, and if you get zero results then create a new object. Then set the fixed_Model attribute of the new/existing object to your new dictionary.

    EDIT

    You are still inserting a new object each time (DataModelSupport *entity = [[DataModelSupport alloc]initWithEntity:descriptor insertIntoManagedObjectContext:context];). See below for an example of "fetch or create":

    AppDelegate *appDelegate  = [[UIApplication sharedApplication]delegate];
    NSManagedObjectContext *context = appDelegate.managedObjectContext ;
    NSEntityDescription *descriptor = [NSEntityDescription entityForName:@"CPIEntity" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc]init];
    request.entity = descriptor;
    NSError *error;
    NSArray *results = [context executeFetchRequest:request error:&error];
    if (results == nil) {
        // This implies an error has occurred.
        NSLog(@"Error from Core Data: %@", error);
    } else {
        if (results.count == 0) {
            // No objects saved, create a new one...
            DataModelSupport *entity = [[DataModelSupport alloc]initWithEntity:descriptor insertIntoManagedObjectContext:context];            
            entity.fixed_Model = newDict;
        } else {
            // At least one object saved.  There should be only one
            // so use the first... 
            DataModelSupport *entity = [results firstObject];
            entity.fixed_Model = newDict;
        }
    }
    

    I've assumed for simplicity that newDict is not nil; amend as appropriate to handle that case.