如何使用“变量值”作为类名(在ObjectiveC中创建一个对象)?

时间:2013-05-26 07:03:56

标签: objective-c

我遇到了问题:

我想使用变量的值来创建一个对象。

例如,我有一个变量myVar

If myVar == 'Client' :  myVar* obj (obj will be an Client instance)
If myVar == 'People' :  myVar* obj (obj will be an People instance)
有人可以帮帮我吗? (对不起我的英文)

1 个答案:

答案 0 :(得分:6)

您可以使用NSClassFromString(@"ClassName")从字符串中获取类。要获取课程的实例,请致电allocinit。例如:

NSString *myString = [NSClassFromString(@"NSString") alloc] init];

如果您不确定要传递给NSClassFromString的哪个班级,或者您想要传递不同的变量,可以使用类型id,如下所示:< / p>

id myObject = [NSClassFromString(myVar) alloc] init];

如果希望Xcode支持该类的属性和方法的代码完成,则可能必须稍后对myObject进行类型转换,或者将其重新分配给类型变量。

你可以read more about NSClassFromString in the developer documentation

修改

由于此处还有一些关于运行时内省以及此代码的“脆弱”性质的讨论,我将再解释一下。 Objective-C运行时支持各种巧妙的技巧,包括从字符串实例化类。当然,你必须确保你首先得到你期望的那种物体。

从NSClassFromString返回的类中实例化对象后要检查的第一件事是对象是nil。如果是,NSClassFromString和alloc之间或者alloc和init之间出错了。我敢打赌你的字符串实际上不是现有的类。所以,一个稍微更安全的方法是这样的:

id myObject = nil;   // Declare a myObject variable. Initialize to nil
Class class = NClassFromString(myVar);

if(!class) 
{ 
  // The class doesn't exist, we can't make the object
}
else 
{
   myObject = [[class alloc] init]; // You can also use [class new] if you're using a vanilla initializer

  if(!myObject) 
  {
     // myObject couldn't be created for some reason...
  }
  else
  {
    // You've got an instance of your class
  }
} 

我想更进一步,因为运行时很棒。

您还可以检查给定对象是否可以执行某些方法。为此,请查看respondsToSelector:。 (选择器的意思是“方法名称”,本质上是一个字符串。)假设我们在myObject中有一个有效的对象,我们可以检查myObject是否可以执行某些操作,比如show

if([myObject respondsToSelector:@selector(show)])
{
   [myObject show]; // Safe to call `show` here
}
else
{
   // Not safe, do something else!
}

我已将show传递给@selector,因为它是UIAlertView.h中定义的有效方法。如果我们不确定选择器的存在会怎么样?好吧,我们可以从字符串创建一个选择器,就像我们在类中一样。这是如何工作的:

SEL selector = NSSelectorFromString(@"myCustomMethod");

if ([myObject respondsToSelector:selector])
{
  [myObject performSelector:selector];
}

我们创建选择器,检查对象是否实现了该方法,如果是,则有效地调用该方法。

当我说你应该检查你得到了你期望的那种对象时,我忘了提到你也可以询问运行时对象的类是否等于给定的类。这是一个例子:

id myObject = [[NSClassFromString(@"UIView") alloc] init];

if([myObject isKindOfClass:[UIView class]])
{
  // We've got a UIView. Set a frame, install it in a hierarchy, or have a drink with it.
}
else
{
  // Mayday!
}

更常见的是,您需要检查特定的行为而不是类,但尝试实例化Class并检查它是否有效可能很有用。当您检查旧版iOS的向后兼容性时,这会有所帮助。

希望这有帮助!