Есть ли способ динамически определять ивары класса во время выполнения в Cocoa / Cocoa Touch? - PullRequest
6 голосов
/ 27 октября 2009

Есть ли способ получить что-то вроде словаря всех пар ключ-значение класса?

Ответы [ 3 ]

8 голосов
/ 27 октября 2009

Вы должны будете бросить свои собственные функции Objective-C Runtime . Вот несколько простых примеров кода. Обратите внимание, что получение ivars класса не получает ivars его суперкласса. Вам нужно сделать это явно, но все функции есть во время выполнения.

#import <objc/objc-runtime.h>
#include <inttypes.h>
#include <Foundation/Foundation.h>

@interface Foo : NSObject
{
    int i1;
}
@end
@implementation Foo
@end

@interface Bar : Foo
{
    NSString* s1;
}

@end
@implementation Bar
@end

int main(int argc, char** argv)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    unsigned int count;
    Ivar* ivars = class_copyIvarList([Bar class], &count);
    for(unsigned int i = 0; i < count; ++i)
    {
        NSLog(@"%@::%s", [Bar class], ivar_getName(ivars[i]));
    }
    free(ivars);


    [pool release];
}
6 голосов
/ 27 октября 2009

Я не уверен, что только для ivars, но если вы определили их как свойства, можно получить доступ к доступным свойствам класса.

Я использовал SQLitePersistentObjects для пары проектов, и у него есть некоторый полезный код, который получает свойства, определенные в классе, для использования при вычислении сериализации в sqlite и из sqlite.

Он использует функцию class_copyPropertyList для получения списка доступных свойств в классе.

Более конкретно:

+(NSDictionary *)propertiesWithEncodedTypes
{

    // DO NOT use a static variable to cache this, it will cause problem with subclasses of classes that are subclasses of SQLitePersistentObject

    // Recurse up the classes, but stop at NSObject. Each class only reports its own properties, not those inherited from its superclass
    NSMutableDictionary *theProps;

    if ([self superclass] != [NSObject class])
        theProps = (NSMutableDictionary *)[[self superclass] propertiesWithEncodedTypes];
    else
        theProps = [NSMutableDictionary dictionary];

    unsigned int outCount;


    objc_property_t *propList = class_copyPropertyList([self class], &outCount);
    int i;

    // Loop through properties and add declarations for the create
    for (i=0; i < outCount; i++)
    {
        objc_property_t * oneProp = propList + i;
        NSString *propName = [NSString stringWithUTF8String:property_getName(*oneProp)];
        NSString *attrs = [NSString stringWithUTF8String: property_getAttributes(*oneProp)];
        NSArray *attrParts = [attrs componentsSeparatedByString:@","];
        if (attrParts != nil)
        {
            if ([attrParts count] > 0)
            {
                NSString *propType = [[attrParts objectAtIndex:0] substringFromIndex:1];
                [theProps setObject:propType forKey:propName];
            }
        }
    }

  free(propList);

    return theProps;    
}

Возвращает словарь свойств - вам нужно будет изучить результаты, которые вы получите, но вы сможете получить то, что вам нужно, если вы используете свойства.

4 голосов
/ 27 октября 2009

Да, вполне возможно:

int numIvars = 0;
Ivar * ivars = class_copyIvarList([anInstanceOfAClass class], &numIvars);
NSMutableDictionary * pairs = [NSMutableDictionary dictionary];
for (int i = 0; i < numIvars; ++i) {
  Ivar ivar = ivars[i];
  NSString * ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
  id ivarValue = [anInstanceOfAClass valueForKey:ivarName];
  [pairs setObject:ivarValue forKey:ivarName];
}
free(ivars);
NSLog(@"%@", pairs);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...