Pull to refresh

Магия в рантайме: инспектируем Objective-C объекты

Reading time 2 min
Views 1.9K
Objective-C, в отличие от иных языков, тип указателя у объектов не имеет особого значения во время исполнения при посылке сообщений и используется лишь во время компиляции. Просто выполните и проверьте:
NSNumber *string = [[NSString alloc] initWithString: @"hello"]; 
NSLog(@"%@", string); 


Вы же не сомневались ;-) Мы бы могли использовать любой тип или вообще id.
Во время исполнения же всю нужную информацию получают у class object, через переменную isa. class object, c типом Class (или просто класс) – это синглтон, и поэтому классы у объектов можно сравнить простым сравнением указателей:
[object class] == [object2 class]; 


Если собрать всё информацию из class object, то несложно восстановить интерфейсы у объектов во время исполнения.


Объекты


// класс: 
- (Class) class; + (Class) class;

// супекласс:
- (Class) superclass; + (Class) superclass;  

// список протоколов: 
Protocol ** class_copyProtocolList(Class cls, unsigned int *outCount); 

// список переменных: 
Ivar * class_copyIvarList(Class cls, unsigned int *outCount); 

// список методов: 
Method * class_copyMethodList(Class cls, unsigned int *outCount); 

// список свойств: 
objc_property_t * class_copyPropertyList(Class cls, unsigned int *outCount); 


Переменные


// имя: 
const char * ivar_getName(Ivar ivar); 

// тип: 
const char * ivar_getTypeEncoding(Ivar ivar); 


Методы


// имя: 
SEL method_getName(Method method); // чтобы перевести его в строку используйте 
sel_getName(method_getName(method));

// количество параметров: 
unsigned method_getNumberOfArguments(Method method); 

// тип параметра с номером index: 
char * method_copyArgumentType(Method method, unsigned int index); 
void method_getArgumentType(Method method, unsigned int index, char *dst, size_t dst_len); 

// тип: 
char * method_copyReturnType(Method method); 
void method_getReturnType(Method method, char *dst, size_t dst_len); 


Свойства


имя, тип и атрибуты:
const char *property_getAttributes(objc_property_t property);

Строки из объектов


У Class, Protocol, SEL можно спросить строку со своим именем:
NSString * NSStringFromClass (Class aClass);
SString * NSStringFromProtocol (Protocol *proto); 
NSString *NSStringFromSelector (SEL aSelector); 


Увы, у Ivar, Method, objc_property_t своих функций нет и, поэтому мне пришлось их написать:
NSString *OIStringFromIvar (Ivar ivar); 
NSString *OIStringFromMethod (Method method); 
NSString *OIStringFromProperty (objc_property_t property); 


К сожалению, не всю информацию можно получить. При компиляции теряются:
#define, typedef, типы объектов и имена параметров в объявлениях методов.

Тип объектов в стиле: @«NSObject» – это недокументированное свойство objc runtime.

Если вы объявили интерфейс:
@interface MyObject : NSObject { 
 NSNumber *number; 
} 
- (void) setNumber: (NSNumber *) number; 
- (NSNumber *) number; 
@end


, то функции:
OIStringFromIvar (ivar);   

// - (void) setNumber: (NSNumber *) number;
OIStringFromMethod (method);  

// - (NSNumber *) number; 
OIStringFromMethod (method);


вернут соответственно:
NSNumber *number
- (void) setNumber: (id) arg1 
- (id) arg1


Ссылки


Object Inspector
Objective-C Runtime Reference
Objective-C Runtime Programming Guide
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+3
Comments 0
Comments Leave a comment

Articles