Как определить тип возвращаемого свойства в Objective-C - PullRequest
19 голосов
/ 20 апреля 2009

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

Ответы [ 6 ]

34 голосов
/ 21 апреля 2009

Вы говорите об интроспекции свойств среды выполнения, которая, как оказалось, 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: T@"NSArray",&,Vstuff
// thanks to Jason Coco for providing the correct string

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

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

17 голосов
/ 12 мая 2009

Дешевый ответ: используйте источник NSObject + Properties здесь .

Он реализует ту же методологию, что описана выше.

4 голосов
/ 20 апреля 2009

Предпочтительным способом является использование методов, определенных в 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.
}
2 голосов
/ 08 мая 2013

Это действительно комментарий, касающийся вопроса, поднятого Грегом Малетиком в ответ на ответ, предоставленный 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

1 голос
/ 20 апреля 2009

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

if([something isKindOfClass:NSArray.class])
     [somethingElse action];
0 голосов
/ 15 июля 2014

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

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

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

...