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代码(CLIxcodebuild
或可能与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有效。只是不是可选项。