Skip to content

Instantly share code, notes, and snippets.

@jidolstar
Created January 15, 2019 13:14
Show Gist options
  • Select an option

  • Save jidolstar/606b6a6d5aa7f7377d94d22d163d91f3 to your computer and use it in GitHub Desktop.

Select an option

Save jidolstar/606b6a6d5aa7f7377d94d22d163d91f3 to your computer and use it in GitHub Desktop.
bsReflection : objective-c
#import <Foundation/Foundation.h>
//Reflection
@interface bsReflection : NSObject
+(NSString*)stringFromClass:(Class)clazz; //ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)classFromString:(NSString*)className; //ํด๋ž˜์Šค ์ด๋ฆ„์œผ๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)classFromObject:(id)object; //๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(NSString*)classNameFromObject:(id)object; //๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)getPropClassOfObject:(id)object key:(NSString*)key; //๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ์˜ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)getPropClassOfClass:(Class)clazz key:(NSString*)key; //ํด๋ž˜์Šค์˜ ํ”„๋กœํผํ‹ฐ์˜ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)getPropClassOfRootObject:(id)object keyPath:(NSString*)keyPath; //๊ธฐ๋ฐ˜๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ keyPath์— ํ•ด๋‹นํ•˜๋Š” ์†์„ฑ์˜ ํด๋ž˜์Šค๋ฅผ ์–ป์–ด์˜จ๋‹ค.
+(Class)getPropClassOfRootClass:(Class)clazz keyPath:(NSString*)keyPath; //๊ธฐ๋ฐ˜ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ keyPath์— ํ•ด๋‹นํ•˜๋Š” ์†์„ฑ์˜ ํด๋ž˜์Šค๋ฅผ ์–ป์–ด์˜จ๋‹ค.
+(NSArray*)getPropNamesOfClass:(Class)clazz superInquiry:(BOOL)superInquiry; //ํด๋ž˜์Šค์˜ ํ”„๋กœํผํ‹ฐ ์ด๋ฆ„์„ ๋ฐฐ์—ด๋กœ ๊ฐ€์ ธ์˜จ๋‹ค. superInquiry๋Š” ํ•ด๋‹นํด๋ž˜์Šค์˜ ๋ถ€๋ชจํด๋ž˜์Šค ํ”„๋กœํผํ‹ฐ๋„ ํƒ์ƒ‰ํ•  ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ํ”Œ๋ž˜๊ทธ๋‹ค.
+(id)getPropValueOfObject:(id)object keyPath:(NSString*)keyPath; //๊ฐ์ฒด์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์„ ๊ฐ€์ง„ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.
+(void)setPropValueOfObject:(id)object keyPath:(NSString*)keyPath value:(id)value; //๊ฐ์ฒด์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์„ ๊ฐ€์ง„ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ์…‹ํŒ…ํ•œ๋‹ค.(KVO, KVC์— ์ ์šฉ์•ˆ๋จ)
+(BOOL)hasPropAtObject:(id)object keyPath:(NSString*)keyPath; //๊ฐ์ฒด์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๊ฐ€?
+(BOOL)hasPropAtClass:(Class)clazz keyPath:(NSString*)keyPath; //ํด๋ž˜์Šค์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๊ฐ€?
@end
#import "bsReflection.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import "bs.h"
@implementation bsReflection
//ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜จ๋‹ค.
+(NSString*)stringFromClass:(Class)clazz {
return NSStringFromClass( clazz );
}
//ํด๋ž˜์Šค ์ด๋ฆ„์œผ๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)classFromString:(NSString*)className {
return NSClassFromString( className );
}
//๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)classFromObject:(id)object {
return [object class];
}
//๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜จ๋‹ค.
+(NSString*)classNameFromObject:(id)object {
return NSStringFromClass( [object class] );
}
//๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ์˜ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)getPropClassOfObject:(id)object key:(NSString*)key {
return [self getPropClassOfClass:[object class] key:key];
}
//ํด๋ž˜์Šค์˜ ํ”„๋กœํผํ‹ฐ์˜ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
+(Class)getPropClassOfClass:(Class)clazz key:(NSString*)key {
const char *nm = [key UTF8String];
objc_property_t p0 = class_getProperty( clazz, nm );
if( p0 == NULL ) {
return NULL;
}
NSString *attr = [NSString stringWithFormat:@"%s", property_getAttributes( p0 )];
NSArray *attrSplit = [attr componentsSeparatedByString:@"\""]; //"T@"NSString",R,V_test"์—์„œ NSString๋งŒ ์ถ”์ถœํ•ด์•ผ ํ•œ๋‹ค.
NSString *className = nil;
if ([attrSplit count] >= 2) {
className = [attrSplit objectAtIndex:1];
}
if( className == nil ) return NULL;
return NSClassFromString( className );
}
//๊ธฐ๋ฐ˜๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ keyPath์— ํ•ด๋‹นํ•˜๋Š” ์†์„ฑ์˜ ํด๋ž˜์Šค๋ฅผ ์–ป์–ด์˜จ๋‹ค.
+(Class)getPropClassOfRootObject:(id)object keyPath:(NSString*)keyPath {
return [self getPropClassOfRootClass:[object class] keyPath:keyPath];
}
//๊ธฐ๋ฐ˜ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ keyPath์— ํ•ด๋‹นํ•˜๋Š” ์†์„ฑ์˜ ํด๋ž˜์Šค๋ฅผ ์–ป์–ด์˜จ๋‹ค.
+(Class)getPropClassOfRootClass:(Class)clazz keyPath:(NSString*)keyPath {
NSArray *names = [bs strSplit:keyPath seperator:@"." trim:NO];
if( [names count] == 0 ) return NULL;
__block Class c = clazz;
[names enumerateObjectsUsingBlock:^(NSString *nm, NSUInteger idx, BOOL *stop) {
objc_property_t p = class_getProperty(c, [nm UTF8String]);
if( !p ) {
*stop = YES;
return;
}
NSString *attr = [NSString stringWithFormat:@"%s", property_getAttributes( p )];
NSArray *attrSplit = [attr componentsSeparatedByString:@"\""];
if ( [attrSplit count] < 2) {
*stop = YES;
c = NULL;
}
NSString *className = [attrSplit objectAtIndex:1];
c = NSClassFromString( className );
}];
return c;
}
//ํด๋ž˜์Šค์˜ ํ”„๋กœํผํ‹ฐ ์ด๋ฆ„์„ ๋ฐฐ์—ด๋กœ ๊ฐ€์ ธ์˜จ๋‹ค. superInquiry๋Š” ํ•ด๋‹นํด๋ž˜์Šค์˜ ๋ถ€๋ชจํด๋ž˜์Šค ํ”„๋กœํผํ‹ฐ๋„ ํƒ์ƒ‰ํ•  ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ํ”Œ๋ž˜๊ทธ๋‹ค.
+(NSArray*)getPropNamesOfClass:(Class)clazz superInquiry:(BOOL)superInquiry{
if( clazz == NULL || clazz == [NSObject class] ) {
return nil;
}
NSMutableArray *r = [[NSMutableArray alloc] init];
unsigned int count, i;
objc_property_t *ps = class_copyPropertyList( clazz, &count );
for( i = 0; i < count; i++ ) {
objc_property_t p = ps[i];
const char *pn = property_getName( p );
if( pn ) {
[r addObject:[NSString stringWithUTF8String:pn]];
}
}
free( ps );
if( superInquiry ) {
NSArray *sr = [self getPropNamesOfClass:[clazz superclass] superInquiry:YES];
if( sr != nil ) [r addObjectsFromArray:sr];
}
return [NSArray arrayWithArray:r];
}
//๊ฐ์ฒด์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์„ ๊ฐ€์ง„ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.
+(id)getPropValueOfObject:(id)object keyPath:(NSString*)keyPath {
NSArray *t0 = [bs strSplit:keyPath seperator:@"." trim:NO];
if( [t0 count] > 0 ) {
__block id t00 = object;
[t0 enumerateObjectsUsingBlock:^(NSString *name, NSUInteger idx, BOOL *stop) {
Ivar ivar = class_getInstanceVariable([t00 class], [[NSString stringWithFormat:@"_%@", name] UTF8String]);
t00 = object_getIvar( t00, ivar );
if( t00 == nil ) *stop = YES;
}];
return t00;
}
return nil;
}
//๊ฐ์ฒด์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์„ ๊ฐ€์ง„ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ์…‹ํŒ…ํ•œ๋‹ค.(KVO, KVC์— ์ ์šฉ์•ˆ๋จ)
+(void)setPropValueOfObject:(id)object keyPath:(NSString*)keyPath value:(id)value {
NSArray *t0 = [bs strSplit:keyPath seperator:@"." trim:NO];
if( [t0 count] > 0 ) {
id t00 = object;
Ivar ivar = nil;
long i = 0, j = [t0 count];
while( 1 ) {
ivar = class_getInstanceVariable([t00 class], [[NSString stringWithFormat:@"_%@", t0[i]] UTF8String]);
if( ++i < j ) {
t00 = object_getIvar( t00, ivar );
if( t00 == nil ) break;
} else {
break;
}
}
object_setIvar( t00, ivar, value );
}
}
//๊ฐ์ฒด์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๊ฐ€?
+(BOOL)hasPropAtObject:(id)object keyPath:(NSString*)keyPath {
return [self hasPropAtClass:[object class] keyPath:keyPath];
}
//ํด๋ž˜์Šค์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๊ฐ€?
+(BOOL)hasPropAtClass:(Class)clazz keyPath:(NSString*)keyPath {
//clazz์™€ name์œผ๋กœ ์บ์‹ฑํ•„์š”!
NSArray *names = [bs strSplit:keyPath seperator:@"." trim:NO];
if( [names count] == 0 ) return NO;
__block Class c = clazz;
__block BOOL has = NO;
NSUInteger maxIdx = [names count] - 1;
[names enumerateObjectsUsingBlock:^(NSString *nm, NSUInteger idx, BOOL *stop) {
objc_property_t p = class_getProperty(c, [nm UTF8String]);
if ( !p ) {
has = NO;
*stop = YES;
return;
}
if( idx == maxIdx ) {
has = YES;
return;
}
NSString *attr = [NSString stringWithFormat:@"%s", property_getAttributes( p )];
NSArray *attrSplit = [attr componentsSeparatedByString:@"\""];
if ( [attrSplit count] < 2) {
has = NO;
*stop = YES;
return;
}
NSString *className = [attrSplit objectAtIndex:1];
c = NSClassFromString( className );
}];
return has;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment