通过名称创建Objective-C类实例吗?


95

是否可以通过名称创建类的实例?就像是:

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

我不知道在Objective-C中这是否可行,但看起来确实如此,

Answers:



38

NSClassFromString()冒着混淆类名或以其他方式使用不存在的类的风险。如果您犯了该错误,直到运行时您都不会发现。相反,如果您使用内置的Objective-C类型Class创建变量,则编译器将验证该类是否存在。

例如,在您的.h

@property Class NameOfClass;

然后在您的.m

id object = [[NameOfClass alloc] init];

如果您输错了类名或它不存在,则在编译时会出现错误。我也认为这是更干净的代码。


哥们,你去了。不确定是否是最好的答案,因为它需要两行内容并且动态性较差,但全都赞成
Chris McCall

我想您可以说它的动态性较差,因为我使用的是符号而不是字符串。但是,如果在编写代码时知道所需的类,则最好使用符号,以避免可能的错别字。
西蒙·伍德赛德

@sbwoodside:这怎么工作?我尝试了一下,然后从链接器中获得了“未定义的体系结构符号”。
拉尔斯·施耐德

将其更改为[[[self class] alloc] init]; 您不需要任何其他东西。
尼克·特纳

OP的用例不仅仅是合法的-它是将对象层次结构序列化为文件/内存块/ plist /任何对象的基础。很多时候,您不事先知道需要实例化哪些类。我的用例是繁琐的工作,需要“注册”大量的“ NSValueTransformer”,而不是复制[NSValueTransformer setValueTransformer:MyTransformerA alloc] init] forName:@“ MyTransformerA”]; 40次-我只扫描了一个变压器名的NSArray-并从字符串创建/注册它们。
Motti Shneor '18 -10-27

8

如果您正在使用Objective-C的工作没有NeXTstepOS XiOSGNUstep等)的系统,或者你只是觉得这个方法更清洁,那么你可以利用Objective-C语言运行时库的API。下Objective-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 + 1NeXTSTEPAPI。


2
@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];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.