在Objective-C确定属性是否为int,float,double,NSString,NSDate,NSNumber等 [英] In Objective-C Determine if a Property is an int, float, double, NSString, NSDate, NSNumber, etc

查看:195
本文介绍了在Objective-C确定属性是否为int,float,double,NSString,NSDate,NSNumber等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要确定一个对象的属性(通过名称传递)类型,以便从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:


  1. valueForKey::如果使用 [myObject valueForKey:@myPropertyName] ,它将返回一个对象。如果属性对应于某种原始类型( int float CGRect ,etc),那么它将被装入一个 NSNumber NSValue 。如果它以 NSNumber 的形式返回,那么您可以轻松地提取一个双重表示( doubleValue ), NSTimeInterval 创建 NSDate 。我可能会推荐这种方法。

  2. 每种类型的特殊情况。 property_getAttributes()返回表示属性的所有属性的 char * ,您可以通过执行this:

  1. 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 an NSNumber or NSValue (as appropriate). If it comes back as an NSNumber, you can then easily extract a double representation (doubleValue) and use that as an NSTimeInterval to create an NSDate. I would probably recommend this approach.
  2. Special case each type. property_getAttributes() returns a char* 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆