Core Dataが私の価値の1つを失うのはなぜですか?

core-data ios objective-c
Core Dataが私の価値の1つを失うのはなぜですか?

ユーザーオブジェクト内には、次のコードがあり、新しい「セッション」を生成するか、既存のセッションを継続します(存在する場合)。

奇妙なことに、他のプロパティは保持されますが、「ユーザー」プロパティは失われます…​ ユーザーはセッションと1対多の関係にあり、1人のユーザーは多くのセッションを持つことができます。 (または、次のテストでは、以前のセッションを単に確認し、存在する場合はそれを使用しています)

-(void)setupSessionStuff
{
// Create new Core Data request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Session" inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];

// Create Sort Descriptors for request
NSSortDescriptor *startTimeSort = [[NSSortDescriptor alloc] initWithKey:@"startTime" ascending:NO selector:nil];
[request setSortDescriptors:[NSArray arrayWithObjects:startTimeSort, nil]];
[startTimeSort release];

[request setFetchLimit:1]; // Only get the most recent session

// Execute request
NSError *error = nil;
NSArray *results = [[self managedObjectContext] executeFetchRequest:request error:&error];
if (results == nil) {
    // Something went horribly wrong...
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    exit(-1);
}
[request release];

Session *theSession = nil;

if ([results count] == 1) {
    NSLog(@"existing session");
    // Use existing Session
    theSession = [results objectAtIndex:0];

    NSLog(@"session.user: %@", [theSession valueForKey:@"user"]); // this is always null!

} else {
    NSLog(@"new session");
    // Create new Sesson
    theSession = (Session *)[NSEntityDescription insertNewObjectForEntityForName:@"Session" inManagedObjectContext:[self managedObjectContext]];

    // Add the Session to the User
    NSLog(@"before: session.user: %@", theSession.user); // null
    theSession.user = self;
    NSLog(@"after: session.user: %@", theSession.user); // looks good
}

...


NSLog(@"before.save: session.user: %@", theSession.user); // good

// Save everything
error = nil;
if (![[self managedObjectContext] save:&error]) {
    // Something went horribly wrong...
    NSLog(@"Unresolved error: %@, %@, %@", error, [error userInfo],[error localizedDescription]);
    exit(-1);
}

NSLog(@"after.save: session.user: %@", theSession.user); // still there..
}

さらに、Core Data sqliteファイルを開き、SQLite Managerで調べました。 セッションテーブルに保存されているユーザーIDを確認できるので、関係が正しく保存されているように見えます。

メソッドの開始時に別のテストとしてこれを追加しました。

NSSet *set = self.session;

for(Session *sess in set) {
    NSLog(@"startTime %@", sess.startTime);
    NSLog(@"user %@", sess.user);

}

奇妙なことに、この場合はユーザーが設定されています!? ここで設定して、後でフェッチ要求を行うときに数行を設定しないでください…​ ?

以下のフィードバックに応えて

「session.user = self」を割り当てた後にこのコードを追加し、両方とも期待される出力を返します。 したがって、問題は後続のフェッチにあるように見えます。

NSLog(@"self.session: %@", self.session);
NSLog(@"self.session: %@", [self valueForKey:@"session"]);

また、self.sessionを使用してセッションにアクセスすると問題を回避できることに同意しますが、ここで何が起こっているかは解決しません。 他の場所では、私は確かに1つのエンティティから別のエンティティに移動することができないので、フェッチがすべてを正しく引き込むことを確信する必要があります。

  0  0


ベストアンサー

最初に、 `self.session`を記録することで、相手側から関係が設定されていることを確認します。 それがnullとして表示される場合、モデルには相互関係が設定されていません。

あなたのフェッチは不十分に構築されていると思います。 最後に使用されたセッションを提供するためにソート記述子に依存していますが、フェッチ制限は1しかありません。 フェッチは既存のすべての `Session`オブジェクトを見つけ、それらをソートしてから最初のオブジェクトを返すと考えるようです。 ただし、並べ替えは最後に実行されるため、フェッチは単一のセッションオブジェクトを検出し(フェッチ制限のため)、その単一オブジェクトに並べ替えを適用します。 これにより、多かれ少なかれランダムな `Session`オブジェクトを扱う可能性が高くなります。

User`オブジェクトである self`との関係にある `Session`オブジェクトのみに関心があるため、おそらくまったくフェッチする必要はありません。 すでにリレーションシップの片側にオブジェクトがある場合、フェッチする必要はなく、リレーションシップをたどるだけです。 本当に必要なことは次のとおりです。

if ([self.session count]==0){
  //...create new session and set relationship
}else{
  //... find latest session
}

この特定のコードチャンクの問題はレポートにあると思います。 戻り値を取得するときは、 self.user`表記を使用しますが、 null`戻り値を取得する場所では、 `valueForKey:`を使用します。

理論上は両方とも同じ値を返しますが、値を返すために同じメカニズムを使用しないため、同じ値を返す必要はありません。 自己ドット表記はアクセサメソッドを呼び出しますが、 `valueForKey:`はクラスの実装の詳細に依存する場合としない場合があります。 「self.session」が「valueForKey:」が返さない値を返すかどうかをテストします。

0


まあ私は問題を発見し、私の問題を解決しました…​

セッションエンティティのメモリアドレスを調べた後、実行ごとにメモリアドレスが変化していることに気付きました。 さらに調査すると、別のクラスで以前にいくつかのコードをテストし、新しいセッションエンティティを作成していましたが、保存はしていませんが、保存されていることがわかりました。

0


タイトルとURLをコピーしました