2011-06-17 4 views
0

私が取り組んでいる新しいアプリケーションのデータ構造を設計しようとしています。コアデータを初めて使用しています。"int"の配列をコアデータにシリアライズ

私は、コアデータの配列の欠如に取り組むのに少し苦労しましたが、私は主に問題を解決しました。

私が残した1つの問題は、オブジェクトタイプの1つに「int」の配列があることです。私はこれらのintの多くを持っているかもしれないので、私は彼らがスペース効率的であることを望みます。私はまた、すぐにそれらにアクセスできるようにしたい。

私の特定のケースでは、intの配列には2つの操作しか実行されません。一つはそれらを反復すること、もう一つは新しいintを追加することです。最も一般的な操作(および私が最も効率的に保つ必要がある操作)は、配列内のすべての値を読み取ることができるだけです。

保存するには、オブジェクトに「バイナリデータ」属性を使用する必要があることがわかります。今私はバイトの配列に "int"をパックする最良の方法を理解しようとしています。

私のアプリは、今のところiOSデバイスでのみ使用されるデータを作成する予定ですが、将来は他のマシンで使用される可能性があるため、私のソリューションはアーキテクチャに依存しませんが、低速プロセッサを搭載し、バッテリ寿命に懸念があるiOSデバイスでは最速です。

私は現在、intが "リトルエンディアン"形式で格納されるようにバイナリデータを設計するつもりです。私のオブジェクトは、NSManagedObjectのサブクラスであり、サイドフィールド(コアデータストレージの一部ではありません)は、値を反復処理するために使用する "int *"ポインタです。

オブジェクトがメモリにフォールトされると、私はc配列を初期化します。エンディアンは、(私はCFByteOrderGetCurrent()を使用して決定するであろう)「リトルエンディアン」であれば、私はこのようなコードで非常に効率的にintの配列を読むことができます:エンディアンがリトルエンディアンではない場合

@property (retain) NSData *data; // Core Data binary attribute 
... 
int *cArray = (int *) [self.data bytes]; 

、ローカルストレージを割り当て、int値を適切にアンパックし、バイナリ属性とc-arrayの両方を変更して最新に保つ必要があります。

フォルトを管理するためにサブクラスにコードを追加します(フォールトアウト時にcArrayをゼロにし、フォールト時に正しく設定する)。

私は本当に好きではありませんが、私にはうまくいくソリューションがあると思います。

私がしようとしていることを誰かがより良い方法で考えることができるなら、本当に感謝します。

また、c-arrayとNSDataまたはコアデータとのやりとりが私に問題を引き起こす原因を誰かが考えることができれば、本当にありがたいです。

おかげで、 ロン

答えて

1

C規格ができること楽しいことがたくさんあります。

  • 奇数サイズのバイト(9が伝統的な)符号付きの数の
  • 奇数表現(例えばサイン大きさを、ものは補完)
  • は、 int
  • 奇数サイズのメモリ表現で
  • 未使用ビット(16の共通に使用される)

私は個人的にint32_tまたは(好ましくは)uint32_tを使い、奇妙なアーキテクチャについては心配しません。バイト順がコンパイル時に知られているので、私はまた、CFByteOrderGetCurrent()を気にしないだろう:(NSDataのは変更できませんので)私もconst int *を使用したい

#include <TargetConditionals.h> 

#if TARGET_RT_LITTLE_ENDIAN 
    insert code here 
#else 
    #error "Big endian architectures not supported yet!" 
#endif 

self.dataは、オブジェクトが障害に変わるまで有効であるという保証もないかもしれません。—一般的なルールは「オブジェクトを存続させて保持したい場合」です。つまり、コアデータはおそらくオブジェクトを保持していると言えます。

最後に、なぜオブジェクトにintポインタを格納する必要がありますか?コピー/自動解放が効果的に自由であるべき

-(const int32_t*)intArray:(size_t*)count { 
    NSData * d = [[self.data copy] autorelease]; 
    *count = [d length]/sizeof(int32_t); 
    return (const int32_t*)[d bytes]; 
} 

、しかし、あなたが繰り返し処理している配列は、あなたが中にself.dataを設定しても変化しないことを保証するのに役立つ:私は単にオンデマンドで生成したいです繰り返し。

+0

詳細な回答をいただきありがとうございます...良いアドバイスがたくさん! – Ron

+0

TC ...もう少し簡単な質問です。上記のコードは、バイナリデータのコピーを作成し、それをオートレースします。私はこれが上記のNSDataオブジェクトの値でコアデータが行うことを信頼しないというあなたのコメントのためだと思いますか? NSDataのCore Dataのコピーが少なくともオートリリースプールの長さで生き残ることは安全だとは思いませんか? – Ron

+0

'copy'は一般に、不変オブジェクトの場合は' retain'と同じですが、反復処理中にオブジェクトのデータを変更した場合は*です。 'a = self.data; self.data = b; do_something_with(a.bytes) 'は完全にクラッシュする権利があります。反復中に 'data'を変更しないと、コピー/オートレリースをスキップすることは安全ですが、パフォーマンスの差はごくわずかです。 –

2

はCoreDataでこれを実行する典型的な方法は、あなたのint型の値を保持するために単一のフィールドを持っているのオブジェクトに1対多の関係を作ることであろう。あなたはこれらのint値がたくさんあると言ったので、これは満足できる解決策にはならないでしょう。

CoreDataエンティティのバイナリタイプにも注意が必要です。バイナリデータが十分に大きい場合には、パフォーマンスに関連する望ましくない問題が発生することがあります。

これらのオプションのいずれも実行可能でないように思われる場合は、CoreDataから従来のデータベースアプローチを使用するより低いレベルのストレージメカニズムに移行し、int値で目的のすべての機能を効率的に実行できる。

+0

アドバイスありがとうございます!私は、コアデータに保存したいいくつかの "配列"に対して1対多の関係を使用していますが、提案したように、この特定の配列にはオーバーヘッドが大きすぎると感じています。バイナリデータに注意するパフォーマンス上の問題は何ですか?データのフォルトイン/アウトが頻繁に起きるときのスローダウンを指していますか?私のint配列は、たかだか数千個以上のエントリを得ることはないと期待しています。これは最大で約10Kです。 – Ron

+0

私が理解するところでは、CoreDataはこれらのフィールドをフォールトできないので、バイナリ属性は赤いフラグです。したがって、それらが属性であるオブジェクトがフェッチされると、メモリ内に常に存在します。私が知っている共通の回避策は、データ属性のみを持つオブジェクトと一対一の関係を作ることです。そのため、関係にフォールトが発生し、必要なときにのみバイナリデータを取得できます。あなたのデータモデルを知らなければ、確かに言うのは難しいかもしれませんが、実際には、より低いレベルのdbソリューションに落とすことを考えるかもしれません。 –

+0

ポールアドバイスありがとう!私の配列はこれを心配するのに十分な大きさだとは思わないが、それは一般的に知っている良い情報だ!私はいくつかの小さな画像とオーディオクリップを持っています。別のエンティティに移動します。 – Ron

関連する問題