在Objective-C确定属性是否为int,float,double,NSString,NSDate,NSNumber等 [英] In Objective-C Determine if a Property is an int, float, double, NSString, NSDate, NSNumber, etc
问题描述
我需要确定一个对象的属性(通过名称传递)类型,以便从XML执行反序列化。我有一些一般的伪代码(但我不确定如何在Objective-C中执行这些比较):
I need to determine an object's property (passed by name) type in order to perform deserialization from XML. I have some general pseudo-code (however I am unsure of how to perform these comparisons in Objective-C):
id object = [[[Record alloc] init] autorelease];
NSString *element = @"date";
NSString *data = @"2010-10-16";
objc_property_t property = class_getProperty([object class], [element UTF8String]);
const char *attributes = property_getAttributes(property);
char buffer[strlen(attributes) + 1];
strcpy(buffer, attributes);
char *attribute = strtok(buffer, ",");
if (*attribute == 'T') attribute++; else attribute = NULL;
if (attribute == NULL);
else if (strcmp(attribute, "@\"NSDate\"") == 0) [object setValue:[NSDate convertToDate:self.value] forKey:element];
else if (strcmp(attribute, "@\"NSString\"") == 0) [object setValue:[NSString convertToString:self.value] forKey:element];
else if (strcmp(attribute, "@\"NSNumber\"") == 0) [object setValue:[NSNumber convertToNumber:self.value] forKey:element];
我浏览了 class_getProperty 和 property_getAttributes ,但我仍然不知道如何做上述比较。
I have looked through the class_getProperty and property_getAttributes, however I am still not sure how to do the above comparisons.
推荐答案
@ Ahruman的答案是正确的,如果你在处理对象。让我建议一些替代方案:
@Ahruman's answer is correct, if you're dealing with objects. Let me suggest some alternatives:
-
valueForKey:
:如果使用[myObject valueForKey:@myPropertyName]
,它将返回一个对象。如果属性对应于某种原始类型(int
,float
,CGRect
,etc),那么它将被装入一个NSNumber
或NSValue
。如果它以NSNumber
的形式返回,那么您可以轻松地提取一个双重表示(doubleValue
),NSTimeInterval
创建NSDate
。我可能会推荐这种方法。 -
每种类型的特殊情况。
property_getAttributes()
返回表示属性的所有属性的char *
,您可以通过执行this:
valueForKey:
: If you use[myObject valueForKey:@"myPropertyName"]
, it will return an object. If the property corresponds to some sort of primitive (int
,float
,CGRect
, etc), then it will be boxed for you into anNSNumber
orNSValue
(as appropriate). If it comes back as anNSNumber
, you can then easily extract a double representation (doubleValue
) and use that as anNSTimeInterval
to create anNSDate
. I would probably recommend this approach.Special case each type.
property_getAttributes()
returns achar*
representing all of the attributes of the property, and you can extract the type by doing this:
const char * type = property_getAttributes(class_getProperty([self class], "myPropertyName"));
NSString * typeString = [NSString stringWithUTF8String:type];
NSArray * attributes = [typeString componentsSeparatedByString:@","];
NSString * typeAttribute = [attributes objectAtIndex:0];
NSString * propertyType = [typeAttribute substringFromIndex:1];
const char * rawPropertyType = [propertyType UTF8String];
if (strcmp(rawPropertyType, @encode(float)) == 0) {
//it's a float
} else if (strcmp(rawPropertyType, @encode(int)) == 0) {
//it's an int
} else if (strcmp(rawPropertyType, @encode(id)) == 0) {
//it's some sort of object
} else ....
这比路易斯的答案更为正确,因为大多数单字符编码,他们不必。 (他的建议假设单字符编码)
This is pedantically more correct than Louis's answer, because while most types have a single-character encoding, they don't have to. (his suggestion assumes a single-character encoding)
最后,如果你在 NSManagedObject
,那么我鼓励查看 NSPropertyDescription
。
Finally, if you're doing this on a subclass of NSManagedObject
, then I would encourage checking out NSPropertyDescription
.
从这些替代方案中,您可能会看到让运行时框对您来说是最简单的。
From these alternatives, you can probably see that letting the runtime box the value for you is probably simplest.
编辑 :
在上面的代码中,您可以像这样提取类名:
From the code above, you can extract the class name like so:
if ([typeAttribute hasPrefix:@"T@"] && [typeAttribute length] > 1) {
NSString * typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)]; //turns @"NSDate" into NSDate
Class typeClass = NSClassFromString(typeClassName);
if (typeClass != nil) {
[object setValue:[self convertValue:self.value toType:typeClass] forKey:element];
}
}
然后代替使用类方法类别转换(即 [NSDate convertToDate:]
),在 self
上创建一个方法,期望类型作为参数。您现在可以这样做:
And then instead of using class method categories to do the conversion (ie, [NSDate convertToDate:]
), make a method on self
that does that for you and accepts the desired type as a parameter. You could (for now) do it like:
- (id) convertValue:(id)value toType:(Class)type {
if (type == [NSDate class]) {
return [NSDate convertToDate:value];
} else if (type == [NSString class]) {
return [NSString convertToString:value];
} ...
}
我的一部分想知道:为什么在地球上你需要这样做的事情?你在做什么?
Part of me is wondering, though: why on earth are you needing to do things this way? What are you making?
这篇关于在Objective-C确定属性是否为int,float,double,NSString,NSDate,NSNumber等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!