objective-ccocoacore-datamagicalrecordmogenerator

Is there a good place to capture Core Data attribute retrieval to override nil string with empty strings instead?


I'm using Core Data with a somewhat complex data model. There are many places where the string attributes are going to be unset and apparently Core Data returns nil in these cases when retrieving the attribute. I'd like to generally override this behavior so that if any string attribute of the data model would return nil it'll return an empty string instead.

On top of Core Data I'm using both mogenerator and Magical Record. All of the entities in my data model inherit either directly or indirectly from an AbstractEntity, so I'm hoping that I can edit mogenerator's human file to somehow capture calls up the line, regardless of whether they use KVC or method calls, and return an empty string if the string attribute is nil. There are similar situations where I'd want to return an empty string if an integer attribute has zero.

Is this possible? Or do I have to override each attribute individually?


Solution

  • It sounds like what you really want is to make the default value for string attributes be an empty string. In most cases you can set a default value for an attribute in the Core Data model editor. That value is automatically assigned to that attribute any time you create a new managed object. But the editor doesn't support using an empty string as the default, so you can't do it there.

    You can make the default value an empty string at run time, though. Data models are editable until you start using them. So a good place to do it is immediately after you create the model object. The following will assign an empty string as the default value for every string attribute in a data model:

    - (NSManagedObjectModel *)managedObjectModel
    {
        if (_managedObjectModel != nil) {
            return _managedObjectModel;
        }
        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyModel" withExtension:@"momd"];
        _managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
    
        NSEntityDescription *entityDescription = [_managedObjectModel entitiesByName][@"Entity"];
        for (NSString *attributeName in [entityDescription attributesByName]) {
            NSAttributeDescription *attributeDesc = [entityDescription attributesByName][attributeName];
            if ([attributeDesc attributeType] == NSStringAttributeType) {
                [attributeDesc setDefaultValue:@""];
            }
        }
    
        return _managedObjectModel;
    }
    

    Use this or something like it, and every string attribute in your model will automatically be an empty string when you create new instances. If you don't want to do this for every string attribute, edit the code to add some extra checks for entity and/or attribute name.