【问题标题】:Is there a way to dynamically determine ivars of a class at runtime in Cocoa / Cocoa Touch?有没有办法在 Cocoa / Cocoa Touch 运行时动态确定类的 ivars?
【发布时间】:2009-10-27 14:52:00
【问题描述】:

有没有办法获得一个类的所有键值对的字典之类的东西?

【问题讨论】:

    标签: objective-c cocoa cocoa-touch


    【解决方案1】:

    您必须使用Objective-C Runtime functions 自行开发。这是一些非常基本的示例代码。请注意,获取类的 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];
    }
    

    【讨论】:

    • 由于class_copyIvarList 的名称中有copy,因此您负责清理内存。因此,您还需要free(ivars);
    • 仅打印 Bar::s1。但是 i1 在哪里?
    【解决方案2】:

    我不确定是否只是 ivars,但如果您将它们定义为属性,则可以访问类上的可用属性。

    我已经在几个项目中使用 SQLitePersistentObjects,它有一些有用的代码可以获取类上定义的属性,以便在确定与 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;    
    }
    

    这将返回一个属性字典 - 您需要对返回的结果进行一些调查,但如果您使用属性,您应该能够获得所需的内容。

    【讨论】:

      【解决方案3】:

      是的,完全有可能:

      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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-02
        • 1970-01-01
        • 2011-01-18
        • 1970-01-01
        • 1970-01-01
        • 2011-01-22
        • 1970-01-01
        • 2019-02-21
        相关资源
        最近更新 更多