У меня есть объект в objective-c во время выполнения, из которого я знаю только ключ KVC, и мне нужно определить тип возвращаемого значения (например, мне нужно знать, является ли его NSArray или NSMutableArray) этого свойства, как можно Я это делаю?
Как определить тип возвращаемого свойства в Objective-C
Ответ 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
.
Ответ 2
Дешевый ответ: используйте источник NSObject + Свойства здесь.
Он реализует ту же методологию, описанную выше.
Ответ 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 и т.д.