43

iPhone SDK でオブジェクトに書き込み可能な @property があるかどうかをテストしたいと思います。

これを行う 1 つの可能な方法は、-valueForKey: メソッドをチェックすることですが、それはかなり洗練されていないようです!

例:

  @try {
    id *value = [instance valueForKey:@"myProperty"];
  }
  @catch (NSException * e) {
    // Key did not exist
  }

これを行うより良い方法はありますか?

4

4 に答える 4

60

チェックされるオブジェクトを作成している場合は、オーバーライドvalueForUndefinedKey:setValue:forUndefinedKeyて、例外を発生させるよりも便利なことを行うことができます。

一方、実行時に知らないオブジェクトをイントロスペクトしようとしている場合は、実行時メソッドを使用してそれを行う必要があります。Objective-C ランタイム自体を使用して、 または を呼び出しclass_copyPropertyListprotocol_copyPropertyListそれらを処理するか、Foundation を使用respondsToSelectorして、特定のプロパティの KVC ゲッター/セッターのオブジェクトをfoo呼び出すことができます[someObject respondsToSelector:NSSelectorFromString(@"foo")];

于 2009-12-08T18:03:14.457 に答える
6

一般に、オブジェクトが特定のキーの値を持っているかどうかを判断する方法はありません。-valueForUndefinedKey:インスタンスは、それ以外の場合は未定義のキーの値をそのメソッドから返すことを決定する場合があります。または、デフォルトの実装が例外をスローする可能性があります。最新の Objective-C (2.0) オブジェクトは、多くの場合、パブリック API で関連するプロパティを宣言します。これらのオブジェクトについては、Objective-C ランタイムのclass_copyPropertyListまたはprotocol_copyPropertyListを使用して、使用可能なプロパティのリストを取得できます。KVC 検索リストをエミュレートしてrepondsToSelector:、インスタンスが適切な getter メソッドに応答するかどうかをテストすることもできます。最後に、ランタイムを使用しclass_copyIvarListて、適切な ivar の ivar をチェックできます。これはあなたがしてはいけない多くの仕事です. valueForKey:メッセージが送信されたときにオブジェクトインスタンスが例外を発生させるかどうかを知ることは保証されず、より大きな問題を示しています...

特定のキーの値をすべて提供する必要があるオブジェクトのコレクションがあり、一部のオブジェクトがそうでない場合は、設計上の問題があります。必要なプロパティを宣言する適切なインターフェイス ( @protocolObjective-C の a) を定義する必要があります。次に、このプロトコルへの準拠をテストするか、コンパイラを使用してコンパイル時の型チェックを行い、インスタンスがプロトコルに準拠していることを確認します (単一のインスタンスを渡す場合)。

于 2009-12-08T18:26:29.273 に答える
0

valueForKey:質問で提案する try/catch アプローチは、例外がスローされるかどうかを知る唯一の信頼できる方法です。

  @try {
    id *value = [instance valueForKey:@"myProperty"];
  }
  @catch (NSException * e) {
    // Key did not exist
  }
于 2020-07-23T02:56:41.690 に答える