UIKit的补充:弥合例如CGRectValue和NSStringFromCGRect之间的差距?

时间:2013-08-10 13:01:38

标签: objective-c uikit objective-c-runtime

我正在尝试实现一个专门的typed记录器,它将字典作为输入并从中创建值字符串。

这样一个字典的示例可能是:

CGSize size = {300, 200} ;
CGAffineTransform t = ::CGAffineTransformIdentity ;

[self logit: @{
    @"columns": @{
        @"value": @3
    ,   @"type": @"NSNumber"
    }
,   @"size": @{
        @"value": [NSValue valueWithCGSize(size)]
    ,   @"type": @"CGSize"
    }
,   @"transform": @{
        @"value": [NSValue valueWithCGAffineTransform(t)]
    ,   @"type":    @"CGAffineTransform"
    }
}] ;

问题是:如何以通用方式检索这些值?

我显然可以写

    for (NSString * key in dict) {
        NSDictionary * params = dict[key] ;

        if ([params[@"type"] isEqualToString: @"CGRect"]) {
            CGRect r = [params[@"value"] CGRectValue] ;
            NSString * s = ::NSStringFromCGRect(r) ;
            ::NSLog(s) ;
        } else if ([params[@"type"] isEqualToString: @"NSNumber"]) {
            ::NSLog(@"%.3f", [params[@"value"] floatValue]) ;
        } else if ([params[@"type"] isEqualToString: @"CGAffineTransform"]) {
            CGAffineTransform t = [params[@"value"] CGAffineTransformValue]
            NSString * s = ::NSStringFromCGAffineTransform(t) ;
            ::NSLog(s) ;
        }
        ...
    }

但我宁愿写一个更“通用”的解决方案。一些事情:

SEL valueSelector = ::NSSelectorFromString([NSString stringWithFormat:@"%@Value", params[@"type"]) ;
NSString * rawCFunctionName = [NSString stringWithFormat:@"NSStringFrom%@", params[@"type"]] ;

所以现在我有一个选择器和一个C函数的名称。

  1. 如何从字符串转到我实际可以调用的C函数?

  2. 使用上面的选择器不清楚,因为它的返回类型可以从id变化,例如:NSNumber *到“普通C对象”,例如:如果是CGRectCGSize等......

  3. 有什么建议吗?

1 个答案:

答案 0 :(得分:2)

  1. 你不能;见“Call a function named in a string variable in C”。

  2. 是的,你必须在编译时知道返回类型。

  3. 然而,一切都没有丢失:你想要做的事情实际上可以以相当普通的方式完成。 NSValue有一个非常好的功能,它的description方法给出的输出非常类似于它所存储类型的适当NSStringFrom...()函数(它可能在引擎盖下使用它们)。例如:

    NSLog(@"%@", [NSValue valueWithCGAffineTransform:CGAffineTransformMake(10, 10, 10, 10, 10, 10)]);
    NSLog(@"%@", [NSValue valueWithCGSize:CGSizeMake(10, 10)]);
    

    的产率:

      

    2013-08-11 03:06:43.053 PrintingNSValue [51538:11303] CGAffineTransform:{{10,10,10,10},{10,10}}
      2013-08-11 03:06:43.055 PrintingNSValue [51538:11303] NSSize:{10,10}

    NSNumber同样可以很好地表达其价值作为描述。

    所以你要做的就是这样:

    for( NSString * key in theDictionary ){
        NSLog(@"%@: %@", key, theDictionary[key][@"value"]);
    }