Question

What I need

I have a bunch of classes generated from my data model that inherit from NSManagedObject. I need a way to get, for any of theses classes, a dictionary of a string of a property name as the key, and the string of it's type as the value, for every property name passed in an array. Or better, in code:

// what I have - generated code
@interface ClassA : NSManagedObject

@property (nonatomic, retain) ClassX *propX;
@property (nonatomic, retain) ClassY *propY;

@end

@implementation ClassA

@dynamic propX;
@dynamic propy;

@end

// what I need
// the method
-(NSDictionary*)dictFromPropNameToPropType:(NSArray*)props {
    //dict being something like @{ @"propX" : @"ClassX", @"propY" : @"ClassY" };
    return dict;
}

// call
dictFromPropNameToPropType(@[@"propX", @"propY"]);

The logic of the dictionary creation is on me. I need a way to get the property class name as a string, giving it's name.

What I've tried

// a instance method of my ClassA
SEL selector = NSSelectorFromString(propertyNameAsString); // like @"propX"
id object = [self performSelector:selector];
Class class = [object class];
NSString *className = NSStringFromClass(class);

and also tried something with dictionaryWithValuesForKeys, but it seems to use the same mechanism and result in the same kind of errors.

No succes there. I get the "class not key value coding-compliant" error for the key passed in as propertyNameAsString, even thou I have the propX property in my ClassA

What I've researched

I've looked the Apple tutorials about KVC and KVO, and also the one about the Runtime (to learn something about the @dynamic auto-generated property). But didn't figure it out on my own.

Edit

With Martin R's answer, I've got this code:

NSMutableDictionary *result = [NSMutableDictionary new];
NSEntityDescription *selfEntity = [self entity];
NSDictionary *relationshipsByName = selfEntity.relationshipsByName;
for (NSString *relationDescription in relationshipsByName) {
    NSRelationshipDescription *relationshipDescription = relationshipsByName[relationDescription];
    NSEntityDescription *destinationEntity = relationshipDescription.destinationEntity;
    result[relationDescription] = destinationEntity.managedObjectClassName;
}
Was it helpful?

Solution

You have subclasses of NSManagedObject, so you can inspect the objects entity, which is a NSEntityDescription.

  • From the entity description, get the propertiesByName, which is a dictionary with the property names as key. The values are NSAttributeDescription or NSRelationshipDescription objects.

  • NSAttributeDescription has a method attributeValueClassName, which is the class representing the attribute (as a string).

  • NSRelationshipDescription has a method destinationEntity which describes the target entity and has a managedObjectClassName method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top