2

私は問題があります :

変数の値を使用してオブジェクトを作成したいと考えています。

たとえば、変数がありますmyVar

If myVar == 'Client' :  myVar* obj (obj will be an Client instance)
If myVar == 'People' :  myVar* obj (obj will be an People instance)

誰かが私を助けることができますか?(私の英語でごめんなさい)

4

1 に答える 1

6

NSClassFromString(@"ClassName")文字列からクラスを取得するために使用します。クラスのインスタンスを取得するには、allocandを呼び出しますinit。例えば:

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

渡すクラスがわからない場合NSClassFromString、または別の変数を渡したい場合は、次のidように type を使用できます。

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

myObjectXcode でそのクラスのプロパティとメソッドのコード補完をサポートする場合は、後で型キャストするか、型付き変数に再割り当てする必要があります。

NSClassFromStringの詳細については、開発者向けドキュメントを参照してください。

編集:

ランタイム イントロスペクションとこのコードの「壊れやすい」性質については、ここで別の議論が行われているので、もう少し説明します。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ました。セレクターの存在について確信が持てなかった場合はどうなるでしょうか。クラスで行ったのと同じように、文字列からセレクターを作成できます。仕組みは次のとおりです。@selectorUIAlertView.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 で下位互換性を確認する場合に役立ちます。

お役に立てれば!

于 2013-05-26T07:05:44.273 に答える