4

I am currently facing the problem to check whether a property of an Object (NSManagedObject) exists or not.

Unfortunately the method

[[MyObject class] respondsToSelector:@selector(myProperty)];

always returns NO.

I think it's because the property generated by CoreData is a new style property ala

@property (nonatomic, strong) NSString *myProperty

So any ideas how to solve this issue?

I would really appreciate all of your suggestions ;)

Thanks in advance! Alex

Alexander
  • 7,178
  • 8
  • 45
  • 75

3 Answers3

15

[[MyObject class] respondsToSelector:...] asks whether the metaobject responds to that selector. So, in effect, it asks whether there is a class method with that selector. Your code would return YES if you had:

+ (NSString *)myProperty;

It returns NO because you have the equivalent of the instance method:

- (NSString *)myProperty;

You need to call respondsToSelector: on an instance of your class.

You could normally use instancesRespondToSelector: directly on the metaclass (so, [MyObject instancesRespondToSelector:...]) but Core Data synthesises the relevant method implementations only when you create an object, so that's a non-starter. You could however create an instance via the normal NSEntityDescription route and test respondsToSelector: on that.

Since it's all Core Data, an alternative would be to ask the NSManagedObjectModel for the relevant NSEntityDescription via its entitiesByName dictionary and inspect the entity description's propertiesByName dictionary.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • 1
    Better answer... I'll remove mine! – jrturton Jan 25 '12 at 13:52
  • Okay, but the problem is, that I do not have an instance object at the point I wanna test this... So are there any other possibilities? – Alexander Jan 25 '12 at 13:54
  • 1
    You'd normally use `instancesRespondToSelector:` directly on `MyObject` but the internals of Core Data make that a non-starter in this case. So you'll need to get Core Data to give you an instance, do a normal `respondsToSelector:` on that and then throw the object away rather than adding it to the persistent store. – Tommy Jan 25 '12 at 13:59
  • Or, alternatively, get the `NSEntityDescription` from the `NSManagedObjectModel` and inspect its `properties` array. I'm updating my answer to comment on this in more detail. – Tommy Jan 25 '12 at 14:03
1

The only cases I've required this has been to set things dynamically so I am only looking for the setter. I am just composing the signature for the setter and then testing that it exists and then using it.

NSArray * keys = [myObject allKeys];
for(NSString * key in keys)
{
    NSString * string = [NSString stringWithFormat:@"set%@:", [key capitalizedString]];
    SEL selector = NSSelectorFromString(string);
    if([myObject respondsToSelector:selector] == YES)
    {
        id object = [dict objectForKey:key];

        // To massage the compiler's warnings avoid performSelector
        IMP imp = [card methodForSelector:selector];
        void (*method)(id, SEL, id) = (void *)imp;
        method(myObject, selector, object);
    }
}

This code satisfies a need where you may not be digesting all the data you receive in the dictionary. In this case it was sparse json, so some data may not always exist in the json so stepping thru myObjects attributes looking for their corresponding key would just be a lot of wasted effort.

EricLeaf
  • 892
  • 5
  • 12
0

Are you synthesizing the property in the class file?

@interface SomeClass : NSObject
{
    @property (nonatomic, strong) NSString *myProperty
}
@end


@implementation SomeClass

    @synthesize myProperty;

@end
Matt MacLean
  • 19,410
  • 7
  • 50
  • 53