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

    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
    Support the author
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 0

    Only users with full accounts can post comments. Log in, please.