Master data does not save transformable NSMutableDictionary

I have two classes: Profile and Config. The profile contains NSSet Config objects. Both profiles and Config are subclasses NSManagedObject.

@interface Profile : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *configs;

- (void)print;

@end

Here is the Config class

@interface Config : NSManagedObject

@property (nonatomic, retain) NSString * otherdata;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSMutableDictionary *myDict;
@property (nonatomic, retain) Profile *profile;

- (void)print;

@end

The myDict dictionary has keys and values NSString*. Now, when I make any changes to myDict, I call the save method NSManagedObjectand it works fine, without errors. Until I kill the application, everything behaves as expected.

But when I forcefully kill the application (either in Xcode, or by double-clicking the home button and killing it in the button bar at the bottom), and then reloading the application, the data in myDict goes back to what it was before, i.e. new data was not actually saved. It was just saved before I killed the application.

myDict Transformable xcdatamodeld. NSTransformer. , MyDictTransformer, Config :

Config.h:

@interface MyDictTransformer : NSValueTransformer

@end

Config.m:

@implementation MyDictTransformer

+ (Class)transformedValueClass
{
    return [NSMutableDictionary class];
}

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

- (id)transformedValue:(id)value
{
    return [NSKeyedArchiver archivedDataWithRootObject:value];
}

- (id)reverseTransformedValue:(id)value
{
    return [NSKeyedUnarchiver unarchiveObjectWithData:value];
}

@end

Config.m :

//
// from: http://stackoverflow.com/questions/4089352/core-data-not-updating-a-transformable-attribute
//

+ (void)initialize {
    if (self == [Config class]) {
        MyDictTransformer *transformer = [[MyDictTransformer alloc] init];
        [NSValueTransformer setValueTransformer:transformer forName:@"MyDictTransformer"];
    }
}

AppDelegate, applicationDidEnterBackground, applicationWillTerminate, saveContext:

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

, , Config. , config.name, config.myDict.

A) ? B) , , NSMutableDictionary ?

+4
1

myDict NSMutableDictionary, .

, myDict - :

someConfig.myDict[@"someKey"] = @"someValue";
[context save:&error];

, setter someConfig, , , . save:, .

, [someConfig didChangeValueForKey:@"myDict"] myDict. , .

myDict non-mutable :

@property (nonatomic, retain) NSDictionary *myDict;
...
NSMutableDictionary *updatedDict = [someConfig.myDict mutableCopy];
updatedDict[@"someKey"] = @"someValue";
someConfig.myDict = [updatedDict copy];
[context save:&error];
+19

Source: https://habr.com/ru/post/1530332/


All Articles