Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C - respondsToSelector for dynamic properties

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

like image 286
Alexander Avatar asked Dec 05 '22 18:12

Alexander


2 Answers

[[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.

like image 61
Tommy Avatar answered Dec 28 '22 22:12

Tommy


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.

like image 31
EricLeaf Avatar answered Dec 29 '22 00:12

EricLeaf