我正在尝试实现一个专门的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函数的名称。
如何从字符串转到我实际可以调用的C函数?
使用上面的选择器不清楚,因为它的返回类型可以从id
变化,例如:NSNumber *
到“普通C对象”,例如:如果是CGRect
,CGSize
等......
有什么建议吗?
答案 0 :(得分:2)
是的,你必须在编译时知道返回类型。
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"]);
}