Самоанализ/Отражение Objective C

Существует ли созданный в методе, функция, API, обычно принимала, что путь, и т.д. вывел содержание инстанцированного объекта в Objective C, конкретно в среде Apple Cocoa/Cocoa-Touch?

Я хочу смочь сделать что-то как

MyType *the_thing = [[MyType alloc] init];
NSString *the_dump = [the_thing dump]; //pseudo code
NSLog("Dumped Contents: %@", the_dump);

и имейте имена переменной экземпляра объекта и отображенные значения, наряду с любыми методами, доступными для вызова во время выполнения. Идеально в легком для чтения формата.

Для разработчиков, знакомых с PHP, я в основном ищу эквивалент отражательных функций (var_dump(), get_class_methods()) и API Reflection OO.

78
задан Cœur 4 April 2019 в 03:19
поделиться

4 ответа

ОБНОВЛЕНИЕ: Любой, кто хочет заниматься подобными вещами, может захотеть проверить оболочку ObjC Майка Эша для среды выполнения Objective-C .

Примерно так можно поступить:

#import <objc/runtime.h>

. . . 

-(void)dumpInfo
{
    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* classDump = [NSDictionary dictionaryWithObjectsAndKeys:
                               ivarArray, @"ivars",
                               propertyArray, @"properties",
                               methodArray, @"methods",
                               nil];

    NSLog(@"%@", classDump);
}

Отсюда легко получить фактические значения свойств экземпляра, но вы должны проверить, являются ли они примитивными типами или объектами, поэтому Мне было лень вставлять его. Вы также могли выбрать сканирование цепочки наследования, чтобы получить все свойства, определенные для объекта. Затем есть методы, определенные по категориям, и многое другое ... Но почти все доступно.

Вот отрывок из того, что приведенный выше код выводит для UILabel:

{
    ivars =     (
        "_size",
        "_text",
        "_color",
        "_highlightedColor",
        "_shadowColor",
        "_font",
        "_shadowOffset",
        "_minFontSize",
        "_actualFontSize",
        "_numberOfLines",
        "_lastLineBaseline",
        "_lineSpacing",
        "_textLabelFlags"
    );
    methods =     (
        rawSize,
        "setRawSize:",
        "drawContentsInRect:",
        "textRectForBounds:",
        "textSizeForWidth:",
        . . .
    );
    properties =     (
        text,
        font,
        textColor,
        shadowColor,
        shadowOffset,
        textAlignment,
        lineBreakMode,
        highlightedTextColor,
        highlighted,
        enabled,
        numberOfLines,
        adjustsFontSizeToFitWidth,
        minimumFontSize,
        baselineAdjustment,
        "_lastLineBaseline",
        lineSpacing,
        userInteractionEnabled
    );
}
112
ответ дан 24 November 2019 в 10:35
поделиться

За исключением метода description (например, .toString () в Java), я не слышал о встроенном , но создать его не составит большого труда. Справочник по времени выполнения Objective-C содержит набор функций, которые можно использовать для получения информации о переменных экземпляра объекта, методах, свойствах и т. Д.

12
ответ дан 24 November 2019 в 10:35
поделиться

Вот что я сейчас использую для автоматической печати переменных класса, в библиотеке для возможного публичного выпуска - это работает путем сброса всех свойств из класса экземпляра по всему дереву наследования. Благодаря KVC вам не нужно заботиться о том, является ли свойство примитивным типом или нет (для большинства типов).

// Finds all properties of an object, and prints each one out as part of a string describing the class.
+ (NSString *) autoDescribe:(id)instance classType:(Class)classType
{
    NSUInteger count;
    objc_property_t *propList = class_copyPropertyList(classType, &count);
    NSMutableString *propPrint = [NSMutableString string];

    for ( int i = 0; i < count; i++ )
    {
        objc_property_t property = propList[i];

        const char *propName = property_getName(property);
        NSString *propNameString =[NSString stringWithCString:propName encoding:NSASCIIStringEncoding];

        if(propName) 
        {
            id value = [instance valueForKey:propNameString];
            [propPrint appendString:[NSString stringWithFormat:@"%@=%@ ; ", propNameString, value]];
        }
    }
    free(propList);


    // Now see if we need to map any superclasses as well.
    Class superClass = class_getSuperclass( classType );
    if ( superClass != nil && ! [superClass isEqual:[NSObject class]] )
    {
        NSString *superString = [self autoDescribe:instance classType:superClass];
        [propPrint appendString:superString];
    }

    return propPrint;
}

+ (NSString *) autoDescribe:(id)instance
{
    NSString *headerString = [NSString stringWithFormat:@"%@:%p:: ",[instance class], instance];
    return [headerString stringByAppendingString:[self autoDescribe:instance classType:[instance class]]];
}
8
ответ дан 24 November 2019 в 10:35
поделиться

Честно говоря, подходящим инструментом для этой работы является отладчик Xcode. В нем вся эта информация легко доступна в наглядной форме. Потратьте время, чтобы научиться им пользоваться, это действительно мощный инструмент.

Дополнительная информация:

Использование отладчика

Устаревшее руководство по отладке Xcode - архивировано Apple

Об отладке в Xcode - архивировано Apple

О LLDB и отладке - архивировано Apple архивировано Apple

Отладка с GDB - архивировано Apple

Руководство по отладке SpriteKit - архивировано Apple

Отладочные темы программирования для Core Foundation - архивировано Apple

3
ответ дан 24 November 2019 в 10:35
поделиться