5

私のiOSプロジェクト内でコアデータモデルを更新するために、私のモデルのマネージエンティティにある程度対応するJSONオブジェクトをサーバーに照会しています。私が目指している最終的な結果は、JSON出力からの信頼できるアップデートソリューションです。NSString型キーに基づいてプロパティの存在と型をテストする方法は?

この質問の例では、コアデータ管理オブジェクトの名前をexistingObjとし、着信JSON逆シリアル化辞書の名前をupdateDictとします。トリッキーな部分は、これらの事実を扱っている:existingObj

  1. ないすべてのプロパティがupdateDictのすべてのプロパティはextistingObjで利用できるわけではありませんupdateDict
  2. に存在しています。
  3. existingObjのプロパティのすべてのタイプがJSONの非直列化プロパティと一致するわけではありません。 (一部の文字列ではカスタムObjective-Cラッパーが必要な場合があります)。
  4. updateDictには、existingObjに初期化されていないキー(nil)の値が含まれている場合があります。

これは、更新されたディクショナリを繰り返し実行している間に、プロパティのテストを前後に行う必要があることを意味します。

// key is an NSString, e.g. @"displayName" 
if ([existingObj respondsToSelector:NSSelectorFromString(key)) { 
    [existingObj setValue:[updateDict objectForKey:key] forKey:key]; 
} 

この部分は動作しますが、私は私が実際だという事実が好きではない:まず、私はupdateDictの性質のようなので、私はKVCを使用して値を設定し、existingObjに存在するかどうかをテストする必要がありますゲッターとしてdisplayNameのテスト、私はsetDisplayName:セッター(KVC経由で間接的に)に電話しようとしています。私はむしろ[existingObj hasWritablePropertyWithName :key]のようなものですが、これは私が見つけることができないものです。

これはサブクエリションのためのものです。A:あなたはプロパティの名前しか持っていない場合、プロパティセッターをどのようにテストしますか?

次の部分は、その種類に基づいてプロパティの識別を自動化したい部分です。 updateDictexistingObjの両方にkey @ "displayName"のNSStringがある場合、新しい値の設定は簡単です。しかし、updateDictに@ "niceShadeOfGreen"というキー@ "color"のNSStringが含まれている場合は、これを正しいUIColorインスタンスに変換したいと思います。しかし、どのように私はexistingObjの受信プロパティの型をテストするので、いつ値を変換するのか、そしていつ割り当てるのですか?私は typeOfSelectorの線に沿って何かを期待していた。もちろん

if ([existingObj typeOfSelector:sel] == [[updateDict objectForKey:key] class]) { 
    // regular assignment 
} else { 
    // perform custom assignment 
} 

これはboguscodeです。私はexistingObjのプロパティの値の型をテストすることに頼ることはできません。それはunitializedまたはnilかもしれません。

サブクラスB:プロパティの名前のみを持つ場合、プロパティのタイプをテストするにはどうすればよいですか?

私はそれだと思います。私はこれが既にここにある何かのものでなければならないと考えましたが、私はそれを見つけることができませんでした。多分あなたたちはできますか?
乾杯、EP。

P.S.カスタムObjective-Cオブジェクトを直列化されていないJSONオブジェクトに同期させるより良い方法がある場合は、共有してください!結局のところ、結果は何を意味します。

+0

あなたが知っている*キーに対して 'updateDict'を問い合わせて、残りの部分はすべて無視することをお勧めします。 – Costique

+0

上記の例から、実際に実行可能なオプションです。しかし現実のシナリオでは、これは管理対象オブジェクトに変更を加え、非常に複雑な更新を行います。オブジェクトは30以上のキー/プロパティで構成され、そのほとんどはNSStringまたはNSNumberです。上記の問題に対する解決策がある場合、両方のプリミティブ型が追加または変更されても、同期化は修正する必要はありません。 – epologee

答えて

27

あなたは、オブジェクトが宣言されたプロパティに対応しkeyと呼ばれる特定のKVCキーのセッターを持っているかどうかを照会したい場合は、最初を大文字に、setで始まる(それはsetKey:と呼ばれるセレクタメソッドに応答するかどうかをチェックする必要があります文字はkeyで、末尾のコロンを追加します)。例えば、

NSString *key = @"displayName"; 
NSString *setterStr = [NSString stringWithFormat:@"set%@%@:", 
         [[key substringToIndex:1] capitalizedString], 
         [key substringFromIndex:1]]; 

if ([obj respondsToSelector:NSSelectorFromString(setterStr)]) { 
    NSLog(@"found the setter!"); 
    [obj setValue:someValue forKey:key]; 
} 

二つの発言:

  • 性質は、上記のパターンに従わない名前のセッターを持つことができるにもかかわらず、彼らはKVC対応ではありませんので、安全です対応する値を設定するためにKVCを使用しているので、set<Key>:を確認してください。

  • KVCはセッターメソッドのみを使用しません。 setterメソッドが見つからない場合は、クラスがインスタンス変数に直接アクセスできるかどうかをチェックし、インスタンス変数を使用する場合はインスタンス変数を使用して値を設定します。また、setterメソッドまたはインスタンス変数が見つからない場合は、-setValue:forUndefinedKey:をレシーバに送信します。このクラスは、例外をスローする標準実装をオーバーライドしている可能性があります。これはKey-Value Coding Programming Guideに記載されています。つまり、常にプロパティを使用している場合は、セッターメソッドのチェックが安全であるはずです。

2番目の質問では、プロパティの実際のObjective-Cクラスを知るためにランタイムをクエリすることはできません。実行時の観点からは、propertiesgeneral types(メソッドのパラメータ/戻り値の型など)の実装固有の型があります。このタイプのエンコーディングはObjective-Cオブジェクトに単一のエンコーディング(つまり@)を使用するため、NSStringプロパティのタイプエンコーディングはObjective-Cクラスであるため、UIColorプロパティのタイプエンコーディングと同じです。

この機能が必要な場合は、クラスを処理し、そのクラスで宣言されているすべてのプロパティ(または興味のあるもの)のキーと対応する型の辞書を返すクラスメソッドを追加し、スーパークラス、または何らかの種類の記述言語を使用することができます。あなた自身でこれを行い、実行時に利用できない情報に頼る必要があります。

+0

非常に貴重な入力@Bavarious。私はそれに対応するタイプの辞書は考えていませんでしたが、これは最も洗練されたソファです!これは、JSONのサーバーレスポンスからローカルモデルを更新する際によくある問題ではありませんか?そのような同期のためのよりよい解決策がありますか?乾杯、EP。 – epologee

+0

それは実際には次の質問の話題になるでしょうが、私は今これを閉じます。ありがとう! – epologee

+0

これは素晴らしいBavariousです、ありがとうございます – shabbirv

関連する問題