如何动态创建类的实例?

时间:2022-06-22 08:56:20

Example:

I have 10 view controllers, which are all allocated and initialized in the same way:

我有10个视图控制器,它们都以相同的方式分配和初始化:

UIViewController *controller = [[MyViewController alloc] initWithNib];

(note that -initWithNib is a custom method of a UIViewController subclass)

(注意-initWithNib是UIViewController子类的自定义方法)

The next view controller class is OtherViewController, and so on. I want to load the view controllers lazily, just when I need them. But to do that, I need to have some kind of "array" that will give me the corresponding class for a given index, so that I can initialize it.

下一个视图控制器类是OtherViewController,依此类推。我想懒洋洋地加载视图控制器,就在我需要的时候。但要做到这一点,我需要有一些“数组”,它将给我一个给定索引的相应类,以便我可以初始化它。

I ended up creating a method with a big switch-statement, that will just do that nasty allocation and initialization separately for every single view controller. I'm not happy with that. There it would be much better if I could assign the appropriate class to a variable, and then at the end of the switch statement just allocate and initialize that class from the variable.

我最终创建了一个带有大型switch语句的方法,它将为每个视图控制器分别进行令人讨厌的分配和初始化。我对此并不满意。如果我可以将适当的类分配给变量,然后在switch语句的末尾,只需从变量中分配和初始化该类,那就更好了。

Is there a way to achieve that?

有没有办法实现这一目标?

EDIT: I've found a function

编辑:我找到了一个功能

id class_createInstance(Class cls, size_t extraBytes)

and every class seems to have a property "class". But I can't assign it to an instance variable. This doesn't work:

每个班级似乎都有一个属性“类”。但我无法将其分配给实例变量。这不起作用:

Class cls = [UIImage class];
cls *image = [cls imageNamed:@"avatar.png"];

The first line compiles. But the second one gives an error: "image undeclared".

第一行编译。但第二个给出了一个错误:“图像未声明”。

5 个解决方案

#1


If you know the names of the classes at compile time, you can assign the classes to Class variables. For example:

如果在编译时知道类的名称,则可以将类分配给类变量。例如:

static Class factory[2];

factory[0] = [MyViewController1 class];
factory[1] = [MyViewController2 class];
...

Then you could have (classid would be a constant known at compile time that would map to a desired class:

那么你可以拥有(classid将是一个在编译时已知的常量,它将映射到所需的类:

-(UIViewController*)createViewController:(int)classid
{
    return [[factory[classid] alloc] init];
}

Assuming that method is defined in a class named MyFactory, you can then do:

假设该方法是在名为MyFactory的类中定义的,那么您可以执行以下操作:

MyFactory * fac = [[MyFactory alloc] init];
UIViewController * v1 = [fac createViewController: 0]; // typed
id v2 = [fac createViewController: 1]; // untyped

If you don't have the compile time name of the class, you can simply do the following:

如果您没有该类的编译时名称,则可以执行以下操作:

#include <objc/objc-runtime.h>

id object = [[NSClassFromString(@"TheClassName") alloc] init];

Since your original question involves a set of UIViewControllers though, there's no reason to lose type safety with the latter method.

由于您的原始问题涉及一组UIViewControllers,因此没有理由使用后一种方法失去类型安全性。

#2


You want to use reflection:

你想使用反射:

 id controller = class_createInstance(NSClassFromString(@"your class name"), 0/*extra bytes*/);

Objective-C Runtime Reference

Objective-C运行时参考

#3


I blogged about this last month at: http://igotosoft.blogspot.com/2009/05/dynamically-creating-viewscontrollers.html Essentially, it involves a new class I call the ClassConstructor, which takes a class name, init method name, and comma separated arguments. When you need to create an instance of that class, just use your [myClassConstructor create];

我上个月在博客上写了这篇文章:http://igotosoft.blogspot.com/2009/05/dynamically-creating-viewscontrollers.html本质上,它涉及一个我调用ClassConstructor的新类,它接受一个类名,init方法名和逗号分隔的参数。当你需要创建该类的实例时,只需使用你的[myClassConstructor create];

#4


What you want is Reflection. No idea of objective-c has it though - but the term might help you Google for your answer better.

你想要的是反思。虽然不知道Objective-c有什么 - 但这个术语可能会帮助你更好地回答谷歌的答案。

#5


The Objective C Reference also will be a good place to look to get the calls. Try searching for Objective-C 2.0 Runtime Reference since I cant add links

Objective C Reference也是一个寻找电话的好地方。尝试搜索Objective-C 2.0运行时参考,因为我无法添加链接

#1


If you know the names of the classes at compile time, you can assign the classes to Class variables. For example:

如果在编译时知道类的名称,则可以将类分配给类变量。例如:

static Class factory[2];

factory[0] = [MyViewController1 class];
factory[1] = [MyViewController2 class];
...

Then you could have (classid would be a constant known at compile time that would map to a desired class:

那么你可以拥有(classid将是一个在编译时已知的常量,它将映射到所需的类:

-(UIViewController*)createViewController:(int)classid
{
    return [[factory[classid] alloc] init];
}

Assuming that method is defined in a class named MyFactory, you can then do:

假设该方法是在名为MyFactory的类中定义的,那么您可以执行以下操作:

MyFactory * fac = [[MyFactory alloc] init];
UIViewController * v1 = [fac createViewController: 0]; // typed
id v2 = [fac createViewController: 1]; // untyped

If you don't have the compile time name of the class, you can simply do the following:

如果您没有该类的编译时名称,则可以执行以下操作:

#include <objc/objc-runtime.h>

id object = [[NSClassFromString(@"TheClassName") alloc] init];

Since your original question involves a set of UIViewControllers though, there's no reason to lose type safety with the latter method.

由于您的原始问题涉及一组UIViewControllers,因此没有理由使用后一种方法失去类型安全性。

#2


You want to use reflection:

你想使用反射:

 id controller = class_createInstance(NSClassFromString(@"your class name"), 0/*extra bytes*/);

Objective-C Runtime Reference

Objective-C运行时参考

#3


I blogged about this last month at: http://igotosoft.blogspot.com/2009/05/dynamically-creating-viewscontrollers.html Essentially, it involves a new class I call the ClassConstructor, which takes a class name, init method name, and comma separated arguments. When you need to create an instance of that class, just use your [myClassConstructor create];

我上个月在博客上写了这篇文章:http://igotosoft.blogspot.com/2009/05/dynamically-creating-viewscontrollers.html本质上,它涉及一个我调用ClassConstructor的新类,它接受一个类名,init方法名和逗号分隔的参数。当你需要创建该类的实例时,只需使用你的[myClassConstructor create];

#4


What you want is Reflection. No idea of objective-c has it though - but the term might help you Google for your answer better.

你想要的是反思。虽然不知道Objective-c有什么 - 但这个术语可能会帮助你更好地回答谷歌的答案。

#5


The Objective C Reference also will be a good place to look to get the calls. Try searching for Objective-C 2.0 Runtime Reference since I cant add links

Objective C Reference也是一个寻找电话的好地方。尝试搜索Objective-C 2.0运行时参考,因为我无法添加链接