Objective-C 2.0: class_copyPropertyList(), как перечислить свойства из категорий
Я попытался перечислить все свойства класса Objective-C, как описано в Objective-C 2.0 Runtime Programming Guide:
id LenderClass = objc_getClass("UIView");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}
Но это перечисляет только три свойства:
userInteractionEnabled Tc,GisUserInteractionEnabled
layer [email protected]"CALayer",R,&,V_layer
tag Ti,V_tag
Глядя на файл заголовка для UIView.h, это три свойства, объявленные непосредственно в классе. Другие свойства UIView добавляются через категории.
Как получить все свойства класса, в том числе из категорий?
Я попробовал это с iPhone-симулятором (iPhone SDK 2.2.1), кстати. (в случае, если это важно).
Ответы
Ответ 1
Основываясь на моих тестах, свойства из категорий будут отображаться при использовании class_copyPropertyList
. Похоже, что свойства, которые вы видите в UIView, описываются только как свойства в публичных заголовках, а не объявлены как таковые при создании самого UIKit. Вероятно, они применили синтаксис свойств, чтобы сделать создание публичных заголовков немного быстрее.
Для справки, здесь мой тестовый проект:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface TestClass : NSObject
{
NSString * str1;
NSString * str2;
}
@property (nonatomic, copy) NSString * str1;
@end
@interface TestClass (TestCategory)
@property (nonatomic, copy) NSString * str2;
@end
@implementation TestClass
@synthesize str1;
@end
@implementation TestClass (TestCategory)
// have to actually *implement* these functions, can't use @synthesize for category-based properties
- (NSString *) str2
{
return ( str2 );
}
- (void) setStr2: (NSString *) newStr
{
[str2 release];
str2 = [newStr copy];
}
@end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([TestClass class], &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}
[pool drain];
return 0;
}
И вот вывод:
str2 [email protected]"NSString",C
str1 [email protected]"NSString",C,Vstr1
Ответ 2
Да, функция class_copyPropertyList возвращает свойства, определенные в категориях.
Что здесь происходит, так это то, что он возвращает свойства, определенные на данном уровне класса, поэтому вы видите только три свойства, определенные в UIView, и ни одно из свойств (нормальное или категориальное), которые определены в UIResponder и Предки NSObject.
Чтобы получить полный унаследованный листинг; вы должны пересечь предков с помощью ссылки Class.superclass и агрегировать результаты класса class_copyPropertyList. Затем вы увидите, например, различные свойства, определенные в категории доступности UIKits для NSObject.
Я действительно пришел сюда, пытаясь исключить из этих результатов свойства, определенные в категориях!