Objective-c에서 객체 속성 목록을 가져옵니다
-
09-09-2019 - |
문제
목록을 어떻게 얻을 수 있습니까 ( NSArray
또는 NSDictionary
객체 C에서 주어진 객체 속성의)?
다음 시나리오를 상상해보십시오. 단지 확장되는 부모 클래스를 정의했습니다. NSObject
, 그것은 그것을 보유하고 있습니다 NSString
, ㅏ BOOL
그리고 NSData
특성으로 개체. 그런 다음이 부모 클래스를 연장하는 몇 가지 수업이있어 각각 다른 속성을 많이 추가합니다.
인스턴스 메소드를 구현할 수있는 방법이 있습니까? 부모의 전체 대상을 거치고 반환하는 클래스는 NSArray
각 (자식) 클래스 속성 중 NSStrings
그것은 ~ 아니다 부모 수업에서 나중에 이것들을 사용할 수 있습니다. NSString
KVC의 경우?
해결책
방금 스스로 답을 얻었습니다. OBJ-C 런타임 라이브러리를 사용하여 원하는 방식으로 속성에 액세스 할 수있었습니다.
- (void)myMethod {
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithCString:propName
encoding:[NSString defaultCStringEncoding]];
NSString *propertyType = [NSString stringWithCString:propType
encoding:[NSString defaultCStringEncoding]];
...
}
}
free(properties);
}
이를 위해서는 'GetPropertytype'C 함수를 만들어야했는데, 이는 주로 Apple 코드 샘플에서 가져온 것입니다 (지금 정확한 소스를 기억할 수 없음).
static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T') {
if (strlen(attribute) <= 4) {
break;
}
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "@";
}
다른 팁
@Boliva의 대답은 좋지만 int, long, float, double 등과 같은 프리미티브를 처리하려면 약간의 추가 기능이 필요합니다.
나는이 기능을 추가하기 위해 그의 것을 만들었습니다.
// PropertyUtil.h
#import
@interface PropertyUtil : NSObject
+ (NSDictionary *)classPropsFor:(Class)klass;
@end
// PropertyUtil.m
#import "PropertyUtil.h"
#import "objc/runtime.h"
@implementation PropertyUtil
static const char * getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
printf("attributes=%s\n", attributes);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T' && attribute[1] != '@') {
// it's a C primitive type:
/*
if you want a list of what will be returned for these primitives, search online for
"objective-c" "Property Attribute Description Examples"
apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc.
*/
return (const char *)[[NSData dataWithBytes:(attribute + 1) length:strlen(attribute) - 1] bytes];
}
else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
// it's an ObjC id type:
return "id";
}
else if (attribute[0] == 'T' && attribute[1] == '@') {
// it's another ObjC object type:
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "";
}
+ (NSDictionary *)classPropsFor:(Class)klass
{
if (klass == NULL) {
return nil;
}
NSMutableDictionary *results = [[[NSMutableDictionary alloc] init] autorelease];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(klass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithUTF8String:propName];
NSString *propertyType = [NSString stringWithUTF8String:propType];
[results setObject:propertyType forKey:propertyName];
}
}
free(properties);
// returning a copy here to make sure the dictionary is immutable
return [NSDictionary dictionaryWithDictionary:results];
}
@end
@Orange80의 답변에는 한 가지 문제가 있습니다. 실제로 0s로 문자열을 종료하는 것은 아닙니다. 이것은 UTF8로 변환하는 동안 충돌과 같은 예상치 못한 결과로 이어질 수 있습니다 (실제로 그 때문에 꽤 성가신 충돌 버그가있었습니다. 디버깅하는 것이 재미있었습니다 ^^). 나는 속성에서 실제로 nsstring을 얻은 다음 cstringusingencoding을 호출하여 그것을 고쳤습니다. 이것은 지금 매력처럼 작동합니다. (또한 적어도 나를 위해 Arc와 함께 작동합니다)
그래서 이것은 지금 내 코드 버전입니다.
// PropertyUtil.h
#import
@interface PropertyUtil : NSObject
+ (NSDictionary *)classPropsFor:(Class)klass;
@end
// PropertyUtil.m
#import "PropertyUtil.h"
#import <objc/runtime.h>
@implementation PropertyUtil
static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
//printf("attributes=%s\n", attributes);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T' && attribute[1] != '@') {
// it's a C primitive type:
/*
if you want a list of what will be returned for these primitives, search online for
"objective-c" "Property Attribute Description Examples"
apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc.
*/
NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
}
else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
// it's an ObjC id type:
return "id";
}
else if (attribute[0] == 'T' && attribute[1] == '@') {
// it's another ObjC object type:
NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
}
}
return "";
}
+ (NSDictionary *)classPropsFor:(Class)klass
{
if (klass == NULL) {
return nil;
}
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(klass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithUTF8String:propName];
NSString *propertyType = [NSString stringWithUTF8String:propType];
[results setObject:propertyType forKey:propertyName];
}
}
free(properties);
// returning a copy here to make sure the dictionary is immutable
return [NSDictionary dictionaryWithDictionary:results];
}
@end
iOS 3.2로 시도했을 때 GetPropertyType 함수는 속성 설명과 잘 어울리지 않습니다. iOS 문서에서 "Objective-C 런타임 프로그래밍 안내서 : 선언 된 속성"에서 예제를 찾았습니다.
다음은 iOS 3.2의 속성 목록에 대한 수정 코드입니다.
#import <objc/runtime.h>
#import <Foundation/Foundation.h>
...
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([UITouch class], &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}
free(properties);
볼리바의 솔루션은 시뮬레이터에서 잘 작동하지만 장치에서는 고정 길이 서브 스트링이 문제를 일으 킵니다. 장치에서 작동하는이 문제에 대한보다 객관적인 C 친화적 솔루션을 작성했습니다. 내 버전에서는 속성의 C- 스트링을 NSSTRING으로 변환하고 문자열 작업을 수행하여 유형 설명의 하위 스트링을 얻습니다.
/*
* @returns A string describing the type of the property
*/
+ (NSString *)propertyTypeStringOfProperty:(objc_property_t) property {
const char *attr = property_getAttributes(property);
NSString *const attributes = [NSString stringWithCString:attr encoding:NSUTF8StringEncoding];
NSRange const typeRangeStart = [attributes rangeOfString:@"T@\""]; // start of type string
if (typeRangeStart.location != NSNotFound) {
NSString *const typeStringWithQuote = [attributes substringFromIndex:typeRangeStart.location + typeRangeStart.length];
NSRange const typeRangeEnd = [typeStringWithQuote rangeOfString:@"\""]; // end of type string
if (typeRangeEnd.location != NSNotFound) {
NSString *const typeString = [typeStringWithQuote substringToIndex:typeRangeEnd.location];
return typeString;
}
}
return nil;
}
/**
* @returns (NSString) Dictionary of property name --> type
*/
+ (NSDictionary *)propertyTypeDictionaryOfClass:(Class)klass {
NSMutableDictionary *propertyMap = [NSMutableDictionary dictionary];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(klass, &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
NSString *propertyName = [NSString stringWithCString:propName encoding:NSUTF8StringEncoding];
NSString *propertyType = [self propertyTypeStringOfProperty:property];
[propertyMap setValue:propertyType forKey:propertyName];
}
}
free(properties);
return propertyMap;
}
이 구현은 Objective-C 객체 유형 및 C 프리미티브와 함께 작동합니다. iOS 8 호환입니다. 이 클래스는 세 가지 수업 방법을 제공합니다.
+ (NSDictionary *) propertiesOfObject:(id)object;
모든 슈퍼 클래스의 객체를 포함하여 객체의 모든 가시적 특성의 사전을 반환합니다.
+ (NSDictionary *) propertiesOfClass:(Class)class;
모든 슈퍼 클래스의 모든 가시적 특성에 대한 사전을 반환합니다.
+ (NSDictionary *) propertiesOfSubclass:(Class)class;
모든 가시 속성의 사전을 반환합니다 특정한 서브 클래스로. 슈퍼 클래스의 속성은 다음과 같습니다 ~ 아니다 포함.
이러한 방법의 사용의 유용한 예 중 하나는 사본 메소드에서 속성을 지정하지 않고 Objective-C에서 하위 클래스 인스턴스에 개체를 복사하십시오.. 이 답변의 일부는이 질문에 대한 다른 답변을 기반으로하지만 원하는 기능에 대한 더 깨끗한 인터페이스를 제공합니다.
헤더:
// SYNUtilities.h
#import <Foundation/Foundation.h>
@interface SYNUtilities : NSObject
+ (NSDictionary *) propertiesOfObject:(id)object;
+ (NSDictionary *) propertiesOfClass:(Class)class;
+ (NSDictionary *) propertiesOfSubclass:(Class)class;
@end
구현:
// SYNUtilities.m
#import "SYNUtilities.h"
#import <objc/objc-runtime.h>
@implementation SYNUtilities
+ (NSDictionary *) propertiesOfObject:(id)object
{
Class class = [object class];
return [self propertiesOfClass:class];
}
+ (NSDictionary *) propertiesOfClass:(Class)class
{
NSMutableDictionary * properties = [NSMutableDictionary dictionary];
[self propertiesForHierarchyOfClass:class onDictionary:properties];
return [NSDictionary dictionaryWithDictionary:properties];
}
+ (NSDictionary *) propertiesOfSubclass:(Class)class
{
if (class == NULL) {
return nil;
}
NSMutableDictionary *properties = [NSMutableDictionary dictionary];
return [self propertiesForSubclass:class onDictionary:properties];
}
+ (NSMutableDictionary *)propertiesForHierarchyOfClass:(Class)class onDictionary:(NSMutableDictionary *)properties
{
if (class == NULL) {
return nil;
}
if (class == [NSObject class]) {
// On reaching the NSObject base class, return all properties collected.
return properties;
}
// Collect properties from the current class.
[self propertiesForSubclass:class onDictionary:properties];
// Collect properties from the superclass.
return [self propertiesForHierarchyOfClass:[class superclass] onDictionary:properties];
}
+ (NSMutableDictionary *) propertiesForSubclass:(Class)class onDictionary:(NSMutableDictionary *)properties
{
unsigned int outCount, i;
objc_property_t *objcProperties = class_copyPropertyList(class, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = objcProperties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithUTF8String:propName];
NSString *propertyType = [NSString stringWithUTF8String:propType];
[properties setObject:propertyType forKey:propertyName];
}
}
free(objcProperties);
return properties;
}
static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T' && attribute[1] != '@') {
// A C primitive type:
/*
For example, int "i", long "l", unsigned "I", struct.
Apple docs list plenty of examples of values returned. For a list
of what will be returned for these primitives, search online for
"Objective-c" "Property Attribute Description Examples"
*/
NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
}
else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
// An Objective C id type:
return "id";
}
else if (attribute[0] == 'T' && attribute[1] == '@') {
// Another Objective C id type:
NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
}
}
return "";
}
@end
누군가가 필요로하는 경우 특성은 부모 클래스에서 상속됩니다 (내가 한 것처럼) 여기에 약간의 수정이 있습니다.오렌지 80"재귀를 만들기위한 코드 :
+ (NSDictionary *)classPropsForClassHierarchy:(Class)klass onDictionary:(NSMutableDictionary *)results
{
if (klass == NULL) {
return nil;
}
//stop if we reach the NSObject class as is the base class
if (klass == [NSObject class]) {
return [NSDictionary dictionaryWithDictionary:results];
}
else{
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(klass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithUTF8String:propName];
NSString *propertyType = [NSString stringWithUTF8String:propType];
[results setObject:propertyType forKey:propertyName];
}
}
free(properties);
//go for the superclass
return [PropertyUtil classPropsForClassHierarchy:[klass superclass] onDictionary:results];
}
}
"속성"이라는 단어는 약간 퍼지입니다. 접근자처럼 보이는 인스턴스 변수, 속성, 메소드를 의미합니까?
세 가지 모두에 대한 대답은 "예,하지만 쉽지는 않습니다." 그만큼 Objective-C 런타임 API 클래스의 IVAR 목록, 메소드 목록 또는 속성 목록을 얻는 기능이 포함되어 있습니다 (예 : class_copyPropertyList()
), 그런 다음 각 유형에 대한 해당 함수로 목록에서 항목의 이름을 얻습니다 (예 : property_getName()
).
대체로, 그것을 올바르게 얻는 것은 많은 일이 될 수 있습니다.
또는 헤더 파일을 읽고 클래스의 "속성"으로 간주되는 것을 찾는 루비/파이썬 스크립트 만 작성할 수 있습니다.
일에 대한 @Orange80의 답변을 얻을 수있었습니다. ARC가 활성화되어 있습니다… ... 내가 원했던 것에 대해 - 적어도 ... 그러나 약간의 시행 착오 없이는 아닙니다. 이 추가 정보가 누군가에게 슬픔을 아끼지 않기를 바랍니다.
구하다 그가 그의 대답으로 설명하는 수업 = 수업으로, 그리고 당신의 AppDelegate.h
(또는 무엇이든), 넣습니다 #import PropertyUtil.h
. 그럼 너의 ...
- (void)applicationDidFinishLaunching:
(NSNotification *)aNotification {
방법 (또는 무엇이든) …
PropertyUtil *props = [PropertyUtil new];
NSDictionary *propsD = [PropertyUtil classPropsFor:
(NSObject*)[gist class]];
NSLog(@"%@, %@", props, propsD);
…
비밀은 클래스의 인스턴스 변수를 캐스트하는 것입니다 (이 경우 내 수업입니다 Gist
, 그리고 나의 인스턴스 Gist
~이다 gist
) 쿼리하고 싶다고 ... nsobject에… (id)
, 등을 잘라 내지 않을 것입니다. 다양한 이상하고 난해한 이유로. 이것은 당신에게 같은 출력을 줄 것입니다 ...
<PropertyUtil: 0x7ff0ea92fd90>, {
apiURL = NSURL;
createdAt = NSDate;
files = NSArray;
gistDescription = NSString;
gistId = NSString;
gitPullURL = NSURL;
gitPushURL = NSURL;
htmlURL = NSURL;
isFork = c;
isPublic = c;
numberOfComments = Q;
updatedAt = NSDate;
userLogin = NSString;
}
OBJC의 "Amazeballs" "Introspection에 대해 Apple의 모든 Apple / OCD 자랑에 대해 ... 그들은이 간단한"외모 ""자신의 자아 ","말하기 "를 쉽게 수행하는 것이 쉽지 않습니다.
그래도 정말로 돼지 와일드 가고 싶다면 .. 확인 .. 클래스 덤프, 이것은 클래스 헤더를 들여다 볼 수있는 마음을 사로 잡는 미친 방법입니다. 모든 실행 파일 등… 실제로 내가 OP의 질문에 대한 해결책을 찾기 시작한 이유입니다. 사용 매개 변수 중 일부는 다음과 같습니다. 즐기십시오!
-a show instance variable offsets
-A show implementation addresses
--arch <arch> choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64)
-C <regex> only display classes matching regular expression
-f <str> find string in method name
-I sort classes, categories, and protocols by inheritance (overrides -s)
-r recursively expand frameworks and fixed VM shared libraries
-s sort classes and categories by name
-S sort methods by name
Boliva가 제공 한 기능을 사용하고 있었지만 iOS 7과의 작업을 중단했습니다. 이제 정적 const char *getPropertype (objc_property_t 속성) 대신 다음을 사용할 수 있습니다.
- (NSString*) classOfProperty:(NSString*)propName{
objc_property_t prop = class_getProperty([self class], [propName UTF8String]);
if (!prop) {
// doesn't exist for object
return nil;
}
const char * propAttr = property_getAttributes(prop);
NSString *propString = [NSString stringWithUTF8String:propAttr];
NSArray *attrArray = [propString componentsSeparatedByString:@","];
NSString *class=[attrArray objectAtIndex:0];
return [[class stringByReplacingOccurrencesOfString:@"\"" withString:@""] stringByReplacingOccurrencesOfString:@"T@" withString:@""];
}
당신은 세 가지 마법 주문이 있습니다
Ivar* ivars = class_copyIvarList(clazz, &count); // to get all iVars
objc_property_t *properties = class_copyPropertyList(clazz, &count); //to get all properties of a class
Method* methods = class_copyMethodList(clazz, &count); // to get all methods of a class.
다음 코드가 도움이 될 수 있습니다.
-(void) displayClassInfo
{
Class clazz = [self class];
u_int count;
Ivar* ivars = class_copyIvarList(clazz, &count);
NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
const char* ivarName = ivar_getName(ivars[i]);
ivarArray addObject:[NSString stringWithCString:ivarName encoding:NSUTF8StringEncoding]];
}
free(ivars);
objc_property_t* properties = class_copyPropertyList(clazz, &count);
NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
const char* propertyName = property_getName(properties[i]);
[propertyArray addObject:[NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
}
free(properties);
Method* methods = class_copyMethodList(clazz, &count);
NSMutableArray* methodArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
SEL selector = method_getName(methods[i]);
const char* methodName = sel_getName(selector);
[methodArray addObject:[NSString stringWithCString:methodName encoding:NSUTF8StringEncoding]];
}
free(methods);
NSDictionary* classInfo = [NSDictionary dictionaryWithObjectsAndKeys:
ivarArray, @"ivars",
propertyArray, @"properties",
methodArray, @"methods",
nil];
NSLog(@"%@", classInfo);
}
이 답변은 도움이되지만 더 많은 것이 필요합니다. 내가하고 싶은 것은 속성의 클래스 유형이 기존 객체의 클래스 유형과 같은지 확인하는 것입니다. 위의 모든 코드는 다음과 같이 할 수 없습니다. 객체의 클래스 이름을 얻으려면 Object_getClassName ()이 다음과 같은 텍스트를 반환합니다.
__NSArrayI (for an NSArray instance)
__NSArrayM (for an NSMutableArray instance)
__NSCFBoolean (an NSNumber object initialized by initWithBool:)
__NSCFNumber (an NSValue object initialized by [NSNumber initWithBool:])
그러나 위의 샘플 코드에서 getPropertytype (...)를 호출하는 경우 4 OBJC_PROPERTY_T CLASS의 속성 구조 : 다음과 같이 정의됩니다.
@property (nonatomic, strong) NSArray* a0;
@property (nonatomic, strong) NSArray* a1;
@property (nonatomic, copy) NSNumber* n0;
@property (nonatomic, copy) NSValue* n1;
문자열을 각각 다음과 같이 반환합니다.
NSArray
NSArray
NSNumber
NSValue
따라서 NSObject가 클래스의 한 속성의 가치가 될 수 있는지 여부는 결정할 수 없습니다. 그럼 어떻게해야하나요?
다음은 내 전체 샘플 코드입니다 (함수 getPropertyType (...)는 위와 동일) :
#import <objc/runtime.h>
@interface FOO : NSObject
@property (nonatomic, strong) NSArray* a0;
@property (nonatomic, strong) NSArray* a1;
@property (nonatomic, copy) NSNumber* n0;
@property (nonatomic, copy) NSValue* n1;
@end
@implementation FOO
@synthesize a0;
@synthesize a1;
@synthesize n0;
@synthesize n1;
@end
static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
//printf("attributes=%s\n", attributes);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T' && attribute[1] != '@') {
// it's a C primitive type:
// if you want a list of what will be returned for these primitives, search online for
// "objective-c" "Property Attribute Description Examples"
// apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc.
NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
}
else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
// it's an ObjC id type:
return "id";
}
else if (attribute[0] == 'T' && attribute[1] == '@') {
// it's another ObjC object type:
NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
}
}
return "";
}
int main(int argc, char * argv[]) {
NSArray* a0 = [[NSArray alloc] init];
NSMutableArray* a1 = [[NSMutableArray alloc] init];
NSNumber* n0 = [[NSNumber alloc] initWithBool:YES];
NSValue* n1 = [[NSNumber alloc] initWithBool:NO];
const char* type0 = object_getClassName(a0);
const char* type1 = object_getClassName(a1);
const char* type2 = object_getClassName(n0);
const char* type3 = object_getClassName(n1);
objc_property_t property0 = class_getProperty(FOO.class, "a0");
objc_property_t property1 = class_getProperty(FOO.class, "a1");
objc_property_t property2 = class_getProperty(FOO.class, "n0");
objc_property_t property3 = class_getProperty(FOO.class, "n1");
const char * memberthype0 = getPropertyType(property0);//property_getAttributes(property0);
const char * memberthype1 = getPropertyType(property1);//property_getAttributes(property1);
const char * memberthype2 = getPropertyType(property2);//property_getAttributes(property0);
const char * memberthype3 = getPropertyType(property3);//property_getAttributes(property1);
NSLog(@"%s", type0);
NSLog(@"%s", type1);
NSLog(@"%s", type2);
NSLog(@"%s", type3);
NSLog(@"%s", memberthype0);
NSLog(@"%s", memberthype1);
NSLog(@"%s", memberthype2);
NSLog(@"%s", memberthype3);
return 0;
}
신속한 구경꾼의 경우이 기능을 활용 하여이 기능을 얻을 수 있습니다. Encodable
기능. 어떻게 설명하겠습니다 :
당신의 객체를 준수하십시오
Encodable
규약class ExampleObj: NSObject, Encodable { var prop1: String = "" var prop2: String = "" }
확장을 만듭니다
Encodable
제공합니다toDictionary
기능public func toDictionary() -> [String: AnyObject]? { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted guard let data = try? encoder.encode(self), let json = try? JSONSerialization.jsonObject(with: data, options: .init(rawValue: 0)), let jsonDict = json as? [String: AnyObject] else { return nil } return jsonDict }
부르다
toDictionary
객체 인스턴스 및 액세스에서keys
재산.let exampleObj = ExampleObj() exampleObj.toDictionary()?.keys
짜잔! 그러한 속성에 액세스하십시오.
for k in exampleObj!.keys { print(k) } // Prints "prop1" // Prints "prop2"