3

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?

4

3 回答 3

2

您应该可以为此使用 NSInvocation。就像是:

// 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];

您也可以使用正确的 objc_msgSend 变体直接执行此操作,但 NSInvocation 更容易(尽管可能慢得多)。

编辑:我在这里放了一个简单的小测试程序。

于 2014-02-04T22:52:56.447 回答
1

这在cocoa-dev上进行了详细讨论。简短的回答是:你不能直接。

但事实证明,有很多方法可以解决这个问题。在您的具体示例中,您应该将这些存储在一个数组中,然后您甚至不需要 KVC 调用。

同样,对于您的具体示例,另一种可能的解决方案是切换到UIBezierPath,它可以CGPath根据您的需要来回转换。

作为一个更通用的解决方案,您可以将它们包装到一个只为您保存价值的对象中,然后将 KVC放在. 这基本上NSValue是包装原始指针的常用方法。

完全通用的解决方案是您可以实现valueForUndefinedKey:、检查密钥并返回您想要的。例如,您可以将路径粘贴在数组中并根据给定的键对其进行索引。或者您可以将它们放在字典中并在那里查找它们(这基本上就是CALayer这样做的)。当然,如果你真的需要它是动态的,你可以对运行时进行内省并基本上重新实现 KVC……这将是非常罕见的正确答案。几乎所有这些“通用”解决方案对于大多数问题来说都是多余的。

简短的回答是,KVC 并不总是能很好地处理非免费桥接的低级对象。

于 2014-02-04T22:48:55.410 回答
0

我会做(有时也会做)是将 CGPathRef 完全包装在 UIBezierPath 中,使其成为一个对象并具有由此产生的所有好处,包括 KVC、将其粘贴在 NSArray 或 NSDictionary 中的能力以及 ARC 内存管理。毕竟,这正是 UIBezierPath什么(或多或少)。

于 2014-02-04T23:15:51.183 回答