2009-09-03 18 views
18

これはiPhoneアプリ用ですが、それは本当に重要ではないと思います。私は、iPhoneのGameKitを使用してブルートゥースでカスタムオブジェクト(コアデータによって管理される)を送信する必要があります。通常、NSKeyedArchiverを使用してオブジェクトをデータオブジェクトとしてパッケージ化し、そのオブジェクトを行間に送り、オブジェクトをアーカイブ解除して終了します。もちろん、自分のカスタムオブジェクトにもinitWithCoder:とencodeWithCoder:メソッドを実装する必要があります。NSManagedObjectのサブクラスをエンコードできますか?

コアデータで管理されているかどうかわからないNSManagedObjectクラスでこれを実行できるかどうかはわかりません。彼らは一緒に素敵なプレーですか?私はエンコードされた管理オブジェクトを他のデバイスに送り、それをエンコードしたら、他のデバイスのコンテキストにこの受け取ったオブジェクトを追加すると思います。これは正しいです?私は何かのステップを逃している?

答えて

27

NSManagedObjectインスタンスが有意義NSManagedObjectContextインスタンスの外に存在することはできませんので、私は(あなたがこれを行うことができます。下記参照)直接NSManagedObject 2間のコンテキストをシリアライズし、デシリアライズするために必要なNSCodingダンスをやろうと気にしないだろう。代わりに、私はinstance.entity.attributesByName.allKeys[instance dictionaryWithValuesForKeys:keys]を使用して属性:値のペアの辞書を得ることができます)を介して、管理対象オブジェクトのインスタンスの属性名を介して属性名を取得することができます。 NSURL -encoded NSManagedObjectIDs。(NSURL)を辞書に含めることを忘れないでください。からまでの関係を再接続できるように、これらの辞書は再帰的に作成する必要がありますエンコードしているインスタンスのリレーションシップの対象

次に、dictをワイヤを介して送信し、もう一方のインスタンスを新しい管理対象のインスタンスとして再構成しますオブジェクトコンテキスト(setValuesForKeysWithDictionary:を使用できます)。

あなたは、これはあなたがカスタムNSDictionaryすべてNSManageObject -to- NSDictionaryマッピングを処理するためのサブクラスとビザと一緒にclassForCoderreplacementObjectForCoder:awakeAfterUsingCoder:を使用する必要があります以外NSCoderシステムは、あなたのために何をするのか、正確であることに気づくことがありその逆。このコードは、直列化しようとしている複雑で深いオブジェクトグラフを持たない限り、私の経験上、それは価値があるよりも面倒です。リレーションシップのない単一のNSManagedObjectインスタンスの場合は、dictへの変換だけで簡単に戻ります。

+0

私はこの同じ問題を抱えていましたが、バリーが示唆していることを正確に行いました。 – jeff7091

+0

それはNSDictionaryの代わりにうまくいくでしょうか、私はNSManagedObjectのモデルと全く同じモデルを持っていますか?そこにマッピングをしますか? – bluezald

+0

NSURLでエンコードされたNSManagedObjectIDがどのように関係に役立つのか誰でも説明できますか?ありがとう! –

2

より簡単なオプションのための辞書ソリューションを提案します。しかし、ここで私はどのように問題を解決したのですか?私のモデルは、既に大規模で堅牢で、カスタムクラスと1つのルートクラスがNSManagedObjectを超えています。 [super initWithEntity:insertIntoManagedObjectContext:]

私が必要なのは、適切な指定イニシャライザNSManagedObjectを呼び出すためにその単一のクラスのためでした。このメソッドとNSEntityDescriptionのメタデータは、すべてのダイナミックアクセサの実装を設定します。

- (id)initWithCoder:(NSCoder *)aDecoder { 
    CoreDataStack *cds = [LibraryDiscoverer unarchivingCoreDataStack]; 
    NSEntityDescription *entity = [cds entityDescriptionForName:[[self class] entityName]]; 
    NSManagedObjectContext *moc = [cds managedObjectContext]; 
    self = [super initWithEntity:entity insertIntoManagedObjectContext:moc]; 
    self.lastEditDate = [aDecoder decodeObjectForKey:@"lastEditDate"]; 
    return self; 
} 

CoreDataStackは、CoreDataを抽象化したものです。 LibraryDiscovererは、コアデータ情報を保持するグローバルアクセスフックです。 entityNameは、クラス名からエンティティ名を提供するために定義されたメソッドです。命名規則(クラス名=エンティティ名)に従うと、一般的に実装できます。

私のクラス階層内の他のすべてのinitWithCoder:メソッドは、標準NSCoderであり、関係の両方向をエンコードする必要はないことに注意してください。CoreDataはそれを再接続します。 (辞書ソリューションを含めて常にそうであるように)

+0

ニースの解決策。 2つのスタックがある場合、これをどのように管理しますか?私は現在、ネットワークを介してアプリケーションの別のインスタンスに通信するアプリケーションに取り組んでいます。私のテストターゲットでは、私はコミュニケーションをテストするユニットテストを持っています。この状況では、私は2つの異なるスタックが必要です。上記の例と組み合わせて、これをどのように解決しますか? –

+0

私は実際に新しい一意のスタックを作成して保存を行い、次にコンテキストを保存します(メインスタックはそれを聞いて更新します)。その後、インポートするスタックを削除します。複雑なunarchivingCoreDataStackForCoder:(NSCoder *)デコーダを取得したい場合は、NSCoder - > stackのマッピングを保持することができます – bshirley

関連する問題