【问题标题】:Create objective-c class instance by name?按名称创建objective-c类实例?
【发布时间】:2010-11-13 12:44:42
【问题描述】:

是否可以按名称创建类的实例?比如:

NSString* className = @"Car";
id* p = [Magic createClassByName:className];
[p turnOnEngine];

我不知道这在objective-c中是否可行,但似乎可以,

【问题讨论】:

    标签: objective-c reflection


    【解决方案1】:
    @interface Magic : NSObject
    + (id)createInstanceOfClass:(Class)classe;
    @end
    
    @implementation Magic
    
    + (id)createInstanceOfClass:(Class)classe
    {
        return [[classe alloc] init];
    }
    
    @end
    

    然后使用它:

    Car *car = [Magic createInstanceOfClass:[Car class]];
    [car engineTurnOn];
    

    【讨论】:

      【解决方案2】:

      NSClassFromString() 冒着错误输入类名或使用不存在的类的风险。如果你犯了那个错误,你直到运行时才会发现。相反,如果您使用 Class 的内置objective-c 类型来创建变量,那么编译器将验证该类是否存在。

      例如,在您的.h:

      @property Class NameOfClass;
      

      然后在你的.m:

      id object = [[NameOfClass alloc] init];
      

      如果你输入了错误的类名或者它不存在,你会在编译时得到一个错误。我也认为这是更干净的代码。

      【讨论】:

      • 好了,伙计。不完全确定这是最好的答案,因为它需要两条线并且不太动态,但都一样
      • 我想你可以说它不那么动态,因为我使用了符号而不是字符串。但是,如果您在编写代码时知道所需的类,那么最好使用该符号以避免可能的拼写错误。
      • @sbwoodside:这怎么行?我试过了,我从链接器中得到了“未定义的架构符号”。
      • 改成[[[self class] alloc] init];你不需要其他任何东西。
      • OP 的用例不仅仅是合法的 - 它是对象层次结构到文件/内存块/plist/whatever 的任何序列化的基础。很多时候,您事先并不知道需要实例化哪些类。我的用例是繁琐的需要“注册”无数个“NSValueTransformer”,而不是重复 [NSValueTransformer setValueTransformer:MyTransformerA alloc] init] forName:@"MyTransformerA"]; 40 次 - 我只是扫描一个 NSArray 的转换器名称 - 并从字符串创建/注册它们。
      【解决方案3】:

      如果您在没有 NeXTstepOS XiOSGNUstep 等)系统的情况下使用 Objective-C,或者您只是认为这种方法更简洁,那么您可以使用 Objective-C language runtime library's APIObjective-C 2.0下:

      #import <objc/runtime.h>
      //Declaration in the above named file
      id objc_getClass(const char* name);
      //Usage
      id c = objc_getClass("Object");
      [ [ c alloc ] free ];
      

      在 Objective-C(1.0 或未命名的版本)下,您将使用以下内容:

      #import <objc/objc-api.h>
      //Declaration within the above named file
      Class objc_get_class( const char* name);
      //Usage
      Class cls = objc_get_class( "Test" );
      id obj = class_create_instance( cls );
      [ obj free ];
      

      我还没有测试过1.0 版本,但是我在现在生产的代码中使用了2.0 函数。我个人认为使用 2.0 函数比使用 NS 函数更干净,因为它占用的空间更少:the length of the name in bytes + 1 ( null terminator ) 用于 2.0 API,the sum of two pointers (isa, cstring)size_t length (cstring_length)length of the string in bytes + 1 用于NeXTSTEP API。

      【讨论】:

        【解决方案4】:
        id object = [[NSClassFromString(@"NameofClass") alloc] init];
        

        【讨论】:

        • 这不会造成任何泄漏吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        • 1970-01-01
        • 2016-02-04
        相关资源
        最近更新 更多