2009-10-27 25 views

Odpowiedz

8

Musisz przeturlać się za pomocą Objective-C Runtime functions. Oto bardzo prosty przykładowy kod. Zauważ, że pobranie ivars z klasy nie daje ivars jej nadklasy. Trzeba to zrobić jawnie, ale wszystkie funkcje są dostępne w środowisku wykonawczym.

#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]; 
} 
+2

Ponieważ '' copy' class_copyIvarList' ma w nazwie, jesteś odpowiedzialny za czyszczenie pamięci. W związku z tym potrzebujesz również "free (ivars);". –

+0

całkowicie w prawo. dzięki. – nall

+0

To tylko druk Bar :: s1. Ale gdzie i1? –

6

Nie jestem pewien tylko dla ivars, ale jeśli masz je zdefiniowane jako właściwości, można uzyskać dostęp do dostępnych właściwości w klasie.

Używam SQLitePersistentObjects dla kilku projektów i ma kilka pomocny kod, który pobiera właściwości zdefiniowane na klasie do użycia przy obliczaniu serializacji do iz sqlite.

Używa funkcji class_copyPropertyList, aby uzyskać dostępną listę właściwości klasy.

Dokładniej:

+(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;  
} 

ta zwraca słownika właściwości - trzeba zrobić kilka bada wyników wrócisz ale powinieneś być w stanie uzyskać to, czego potrzebujesz, jeśli jesteś używając właściwości.

4

Tak, całkowicie możliwe:

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); 
Powiązane problemy