2012-03-05 5 views
4

私はiOS5アプリケーションでインポートしようとしているレールアプリからのプレイスのリストを持っています。各プレイスには、プレイス自体の親があります。私は辞書コアデータ:エントリを検索または挿入/重複してツリー構造をインポート

- (void)initWithDictionary:(NSDictionary *)dictionary { 
    self.placeId = [dictionary valueForKey:@"id"]; 
    id parent = [dictionary objectForKey:@"parent"]; 
    if (parent && parent != [NSNull null]) { 
     NSDictionary *parentDictionary = parent; 
     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"placeId = %@", [parentDictionary objectForKey:@"id"]]; 
     NSArray *matching = fetchedWithPredicate(@"Place", self.managedObjectContext, predicate, nil); 
     if ([matching count] > 0) { 
      self.parent = [matching objectAtIndex:0]; 
     } else { 
      self.parent = [NSEntityDescription insertNewObjectForEntityForName:@"Place" inManagedObjectContext:self.managedObjectContext]; 
      [self.parent initWithDictionary:parentDictionary]; 
     } 
    } 
} 

fetchedWithPredicateを使用してコアデータとそのJSONデータをインポートしようとしている

は私もPlace.mで検証メソッドを持っているように

NSArray* fetchedWithPredicate(NSString *entityName, NSManagedObjectContext *context, NSPredicate *predicate, NSError **error) { 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    [request setIncludesPendingChanges:YES]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context]; 
    [request setEntity:entity]; 
    [request setPredicate:predicate]; 
    NSArray *result = [context executeFetchRequest:request error:error]; 
    return result; 
} 

として定義されたメソッドであります同じplaceId(placeIdはサーバー側のID)で配置するように作成しないようにします。

- (BOOL)validatePlaceId:(id *)value error:(NSError **)error { 
    if (*value == nil) 
     return YES; 

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"placeId = %@ AND (NOT self IN %@)", *value, [NSArray arrayWithObject:self]]; 
    NSArray *matching = fetchedWithPredicate(@"Place", self.managedObjectContext, predicate, error); 
    if ([matching count] > 0) { 
     return NO; 
    } 
    else { 
     return YES; 
    } 
} 

データをインポートするには、サーバーからすべての場所を取得し、JSON形式で戻します。 各プレイスには、独自の情報と、親に関する情報を持つ子ノードがあります。つまり、複数の子の各親が複数回表示されます。私は未保存の変更を含むフェッチし、大丈夫だろう、「検索または作成」の一種を行い、上記のコードを考え

{ "id": 73, 
    "name": "Some place", 
    "parent": { "id": 2, 
       "name": "Parent's name"} 
} 

ように見えます。 しかし、それはまだいくつかの場所の複数のエントリを作成しようとします(そして、そこにバリデーションがあるので失敗します)。深く見ると、実際には同じ場所ID(異なるポインタ)の異なるコアデータオブジェクトが挿入されますが、理由はわかりません。

おかげ

答えて

3

すでに(明らかに良いです)、IDの一意のインデックスを持っているようですね。フェッチで返されることを期待する前に、新しく挿入された作品をコアデータに保存していないと思います。シンプルな(おそらくあまりにも多くの行を持つことに応じてパフォーマンスが悪い場合)は、各オブジェクトが挿入/挿入された直後にsaveContextコールを追加することです。

もう1つの方法は、キーがIDでオブジェクトが値である別の辞書を作成するメモリ内の2つのパスで行うことです。そうすれば、各IDが一度しか存在しないようにすることができます。それらの辞書がすべて辞書に入ったら、簡単に(または簡単に、おそらく)すべてをCore Dataに追加できます。

+0

私は「setIncludesPendingChanges:YES」を有すると考え、私のフェッチにするには、オブジェクトを取得するのに十分でしたコンテキストを保存していないのに現在のコンテキスト。なぜこれが間違っているのか知っていますか? その答えがない限り、別の辞書の提案は私がやることです。 – Nycen

+1

私はpendingChanges(ここで推測)は、メインスレッド/実行ループ上にいる場合は定期的に呼び出されるはずですが、各ループに対して通常の '[moc processPendingChanges]'コールを追加するかどうかだけを知るかもしれないと思います。 –

0

そうで、もう少し調査した後、それは...

私は名前で私のデータをソートされたという事実によるものですので、場所はAには5人の子供を持っていた、そのうちの3だった名前を持っていた場合Aの名前の前に、コードがなります

  1. を作成したもの(私のJSONは、親の親についてに関する情報を返さないため)任意の親自体を持っていない親を持つ3人の子供
  2. を作成します
  3. Aを親として持つ他の2人の子供を作成する(恐らく親がある親は

ここでは、2つのオブジェクトA、1つは親を持ち、もう1つは親なし、もう1つはコアデータ2つのオブジェクトがあると考えてください。

簡単な方法:私のツリーはネストされたセットなので、左の値で場所を並べ替えるだけです。このようにして、私はいつも子供の前に親を作成します。

「名前による並べ替えは、」私の記述の一部ではなかったので、受け入れられたように私は、SCCの答えを残しておきます:)

関連する問題