Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 使用反射的属性类型或类_Objective C_Reflection_Deserialization_Introspection - Fatal编程技术网

Objective c 使用反射的属性类型或类

Objective c 使用反射的属性类型或类,objective-c,reflection,deserialization,introspection,Objective C,Reflection,Deserialization,Introspection,我想知道是否有可能确定对象属性的类或基本类型。获取所有属性名称和值非常容易 那么,当属性没有值或无值时,是否有任何方法可以获取属性类类型 示例代码 @interface MyObject : NSObject @property (nonatomic, copy) NSString *aString; @property (nonatomic, copy) NSDate *aDate; @property NSInteger aPrimitive; @end

我想知道是否有可能确定对象属性的类或基本类型。获取所有属性名称和值非常容易

那么,当属性没有值或无值时,是否有任何方法可以获取属性类类型

示例代码

@interface MyObject : NSObject
@property (nonatomic, copy) NSString *aString;
@property (nonatomic, copy) NSDate *aDate;
@property                   NSInteger aPrimitive;
@end

@implementation MyObject
@synthesize aString;
@synthesize aDate;
@synthesize aPrimitive;

- (void)getTheTypesOfMyProperties {
    unsigned int count;
    objc_property_t* props = class_copyPropertyList([self class], &count);
    for (int i = 0; i < count; i++) {
        objc_property_t property = props[i];

        // Here I can easy get the name or value
        const char * name = property_getName(property);

        // But is there any magic function that can tell me the type?
        // the property can be nil at this time
        Class cls = magicFunction(property);
    }
    free(props);
}

@end
@接口MyObject:NSObject
@属性(非原子,副本)NSString*aString;
@属性(非原子,副本)NSDate*aDate;
@不动产继承人;
@结束
@实现MyObject
@综合收敛;
@合成aDate;
@合成先验知识;
-(void)获取MyProperties的类型{
无符号整数计数;
objc_property_t*props=class_copyPropertyList([self class],&count);
for(int i=0;i
根据搜索结果,我终于找到了它。我只想分享我的结果

unsigned int count;
objc_property_t* props = class_copyPropertyList([MyObject class], &count);
for (int i = 0; i < count; i++) {
    objc_property_t property = props[i];
    const char * name = property_getName(property);
    NSString *propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
    const char * type = property_getAttributes(property);
    NSString *attr = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];

    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 {
        // According to Apples Documentation you can determine the corresponding encoding values
    }

    if ([typeAttribute hasPrefix:@"T@"]) {
        NSString * typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)];  //turns @"NSDate" into NSDate
        Class typeClass = NSClassFromString(typeClassName);
        if (typeClass != nil) {
            // Here is the corresponding class even for nil values
        }
    }

}
free(props);
无符号整数计数;
objc_property_t*props=class_copyPropertyList([MyObject class],&count);
for(int i=0;i
受@arndt bieberstein的ObjC答案的启发,我在Swift 3中编写了一个解决方案(可能与早期版本的Swift非常相似,如果不相同的话)。您可以在上找到它,我正在尝试制作一个pod,但是我在使用Swift 3代码(CLI
xcodebuild
或可能与Xcode 8相关的问题)时遇到了问题。无论如何,类方法
func getTypesOfProperties(包括类clazz:NSObject.Type)->Dictionary?
可以提取从
NSObject
继承的任何Swift类的名称和类型

项目的工作重点是以下方法,但请在以下位置查看完整代码:

您还可以尝试将
Any
强制转换为
NSObject.Type
,这将成功转换从
NSObject
继承的所有属性,然后您可以使用标准的
=
运算符检查类型:

func checkPropertiesOfBook() {
    guard let types = getTypesOfProperties(inClass: Book.self) else { return }
    for (name, type) in types {
        if let objectType = type as? NSObject.Type {
            if objectType == NSDate.self {
                print("Property named '\(name)' has type 'NSDate'")
            } else if objectType == NSString.self {
                print("Property named '\(name)' has type 'NSString'")
            }
        }
    }
}
func ==(rhs: Any, lhs: Any) -> Bool {
    let rhsType: String = "\(rhs)"
    let lhsType: String = "\(lhs)"
    let same = rhsType == lhsType
    return same
}
如果您声明此自定义
==
运算符:

func checkPropertiesOfBook() {
    guard let types = getTypesOfProperties(inClass: Book.self) else { return }
    for (name, type) in types {
        if let objectType = type as? NSObject.Type {
            if objectType == NSDate.self {
                print("Property named '\(name)' has type 'NSDate'")
            } else if objectType == NSString.self {
                print("Property named '\(name)' has type 'NSString'")
            }
        }
    }
}
func ==(rhs: Any, lhs: Any) -> Bool {
    let rhsType: String = "\(rhs)"
    let lhsType: String = "\(lhs)"
    let same = rhsType == lhsType
    return same
}
然后,您甚至可以检查
值类型的类型,如下所示:

class Book: NSObject {
    let title: String
    let author: String?
    let numberOfPages: Int
    let released: Date
    let isPocket: Bool

    init(title: String, author: String?, numberOfPages: Int, released: Date, isPocket: Bool) {
        self.title = title
        self.author = author
        self.numberOfPages = numberOfPages
        self.released = released
        self.isPocket = isPocket
    }
}

guard let types = getTypesOfProperties(inClass: Book.self) else { return }
for (name, type) in types {
    print("'\(name)' has type '\(type)'")
}
// Prints:
// 'title' has type 'NSString'
// 'numberOfPages' has type 'Int'
// 'author' has type 'NSString'
// 'released' has type 'NSDate'
// 'isPocket' has type 'Bool'
func checkPropertiesOfBook() {
    guard let types = getTypesOfProperties(inClass: Book.self) else { return }
    for (name, type) in types {
        if type == Int.self {
            print("Property named '\(name)' has type 'Int'")
        } else if type == Bool.self {
            print("Property named '\(name)' has type 'Bool'")
        }
    }
}
限制
值类型
为可选值时,我还无法为该项目提供支持。如果您在NSObject子类中声明了如下属性:
var myoptionant:Int?
我的解决方案将不起作用,因为方法
class\u copyPropertyList
找不到这些属性


有人对此有解决方案吗?

您的if语句不是多余的吗?如果typeAttribute有这个前缀,它的长度不是自动大于1吗,因为前缀是2个字符?知道这个很好,我很高兴找到了你的答案!这对于将bullsh*t解析为ObjC类来说是非常好的,例如,当API人员决定将所有内容作为字符串发送时:(:(:)谢谢你的回答!想补充一点,根据文档,不同的整数类型编码不同:int->TI,long->TL,long->TQ.BTW,“TQ”文档中没有一个。我们确定UTF8Encoding对于属性名是正确的吗?这在id类型上有一个棘手的错误——id属性的编码只是“t@”,因此它将通过最后一个if检查,但是[typeAttribute length]-4将是否定的,事情会爆炸。请参阅中的我的答案,我可以使用class_copyPropertyList在Obj-C中找到可选项。我得到的唯一警告是NSKeyedUnachiver似乎在尝试从CoreData读回可选NSNumber blob时抛出异常。常规NSNumber有效。只是不是可选项。