Search code examples
objective-ccgpathkvc

How can I access non-KVC compliant properties with just their name?


Context: I have several CGPathRef's in a custom class, derived from NSObject, named model. I'm looking for a way to return a specific CGPathRef, based one a string I generate at runtime.

Simplified Example, if I could use KVC:

#model.h
@property (nonatomic) CGMutablePathRef pathForwardTo1;
@property (nonatomic) CGMutablePathRef pathForwardTo2;
@property (nonatomic) CGMutablePathRef pathForwardTo3;
...


#someVC.m
-(void)animateFromOrigin:(int)origin toDestination:(int)destination{
    int difference = abs(origin - destination);
        for (int x =1; x<difference; x++) {
            NSString *pathName = [NSString stringWithFormat:@"pathForwardTo%d", x];
            id cgPathRefFromString = [self.model valueForKey:pathName];
            CGPathAddPath(animationPath, NULL, cgPathRefFromString);
        }
}

Question: How can I access non-KVC compliant properties (CGPathRef) with just their name represented as a string?


Solution

  • You should be able to use NSInvocation for this. Something like:

    // Assuming you really need to use a string at runtime. Otherwise, hardcode the selector using @selector()
    SEL selector = NSSelectorFromString(@"pathForwardTo1");
    NSMethodSignature *signature = [test methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:selector];
    [invocation setTarget:test];
    [invocation invoke];
    
    CGMutablePathRef result = NULL;
    [invocation getReturnValue:&result];
    

    You can also do it directly with the proper objc_msgSend variant, but NSInvocation is easier (though probably significantly slower).

    EDIT: I put a simple little test program here.