Подтвердить что ты не робот

Как определить тип возвращаемого свойства в Objective-C

У меня есть объект в objective-c во время выполнения, из которого я знаю только ключ KVC, и мне нужно определить тип возвращаемого значения (например, мне нужно знать, является ли его NSArray или NSMutableArray) этого свойства, как можно Я это делаю?

4b9b3361

Ответ 1

Вы говорите об интроспекции свойства runtime, которая, оказывается, является тем, что Objective-C очень хорошо в.

В случае, описанном вами, я предполагаю, что у вас есть класс, подобный этому:

@interface MyClass
{
    NSArray * stuff;
}
@property (retain) NSArray * stuff;
@end

Что закодировано в XML что-то вроде этого:

<class>
    <name>MyClass</name>
    <key>stuff</key>
</class>

Из этой информации вы хотите воссоздать класс, а также дать ему соответствующее значение для stuff.

Вот как это выглядит:

#import <objc/runtime.h>

// ...

Class objectClass;       // read from XML (equal to MyClass)
NSString * accessorKey;  // read from XML (equals @"stuff")

objc_property_t theProperty =
    class_getProperty(objectClass, accessorKey.UTF8String);

const char * propertyAttrs = property_getAttributes(theProperty);
// at this point, propertyAttrs is equal to: [email protected]"NSArray",&,Vstuff
// thanks to Jason Coco for providing the correct string

// ... code to assign the property based on this information

Документация Apple (связанная выше) содержит все грязные сведения о том, что вы можете ожидать в propertyAttrs.

Ответ 3

Предпочтительным способом является использование методов, определенных в NSObject Protocol.

В частности, чтобы определить, является ли что-либо экземпляром класса или подкласса этого класса, вы используете -isKindOfClass:. Чтобы определить, является ли что-то экземпляром определенного класса, и только этот класс (т.е. Не подкласс), используйте -isMemberOfClass:

Итак, для вашего случая вы хотите сделать что-то вроде этого:

// Using -isKindOfClass since NSMutableArray subclasses should probably
// be handled by the NSMutableArray code, not the NSArray code
if ([anObject isKindOfClass:NSMutableArray.class]) {
    // Stuff for NSMutableArray here
} else if ([anObject isKindOfClass:NSArray.class]) {
    // Stuff for NSArray here

    // If you know for certain that anObject can only be
    // an NSArray or NSMutableArray, you could of course
    // just make this an else statement.
}

Ответ 4

Это действительно комментарий, посвященный проблеме, поднятой Грегом Малецем в ответ на ответ, представленный e.James 21APR09.

Согласился, что Objective-C может использовать лучшую реализацию для получения этих атрибутов. Ниже приведен метод, который я быстро скомпоновал для извлечения атрибутов свойства одного объекта:

- (NSArray*) attributesOfProp:(NSString*)propName ofObj:(id)obj{

    objc_property_t prop = class_getProperty(obj.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:@","];
    return attrArray;
}

Частичный список ключей атрибутов:

  • R Только для чтения
  • C Копия последнего назначенного значения
  • & Ссылка на последнее присвоенное значение
  • N Неатомное свойство
  • W Слабая ссылка

Полный список на Apple

Ответ 5

Вы можете использовать сообщение isKindOfClass

if([something isKindOfClass:NSArray.class])
     [somethingElse action];

Ответ 6

Если вы знаете, что свойство определено:

        id vfk = [object valueForKey:propertyName];
        Class vfkClass = vfk.class;

И сравните с isKindOfClass, isSubClass и т.д.