Почему Core Data теряет одно из моих значений? - PullRequest
0 голосов
/ 15 августа 2011

Внутри моего пользовательского объекта у меня есть следующий код для создания нового «сеанса» или продолжения существующего сеанса, если таковой существует.

Странно, что он будет сохранять другие свойства, но просто теряет свойство 'user' ... пользователь имеет отношение один-ко-многим с сеансом, 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. Это выглядит как будто отношения были сохранены правильно, так как я вижу идентификатор пользователя, сохраненный в таблице сеанса.

-

Только что добавил это в начале моего метода в качестве еще одного теста.

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 позволит мне обойти мою проблему, но это не решит, что здесь происходит. В других местах я, конечно, не смогу ходить от одного существа к другому, поэтому нужно быть уверенным, что выборка все правильно вытащит.

Ответы [ 2 ]

0 голосов
/ 18 августа 2011

Ну, я нашел проблему и решил свою проблему ...

После изучения адреса памяти моего объекта сеанса я заметил, что он меняется между запусками.В ходе дальнейших исследований я обнаружил, что там, где я ранее тестировал некоторый код в другом классе, создавая новую сущность сеанса, , но не сохраняя ее , ну, в конце концов, она сохранялась - когда я выполнял сохранение в моемкод выше!

0 голосов
/ 15 августа 2011

Во-первых, я бы проверил, что отношения установлены с другой стороны, зарегистрировав self.session.Если это показывает как ноль, то в модели не установлены взаимные отношения.

Я думаю, что ваша выборка плохо построена.Вы полагаетесь на дескриптор сортировки, чтобы предоставить последний использованный сеанс, но у вас есть предел выборки только 1. Вы, кажется, думаете, что выборка найдет все существующие Session объекты, отсортирует их и затем вернет первый.Однако сортировки выполняются последними, поэтому выборка найдет один объект сеанса (из-за ограничения выборки) и затем применяет сортировку к этому единственному объекту.Это повышает вероятность того, что вы будете иметь дело с более или менее случайным Session объектом.

Вероятно, вам вообще не нужна выборка, потому что вы заинтересованы только в объектах Session, которые связаны с объектом User, который равен self.Если у вас уже есть объект на одной стороне отношений, вам не нужно извлекать, вам просто нужно пройти отношения.Все, что вам действительно нужно сделать, это:

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

Я думаю, что ваша проблема с этим конкретным фрагментом кода заключается в отчетности.Когда вы получаете возвращаемое значение, вы используете нотацию self.user, но там, где вы получаете null возврат, вы используете valueForKey:.

Хотя в теории оба возвращают одно и то же значение, им это не нужно, поскольку они не используют один и тот же механизм для возврата значения.Нотация собственной точки вызывает метод доступа, тогда как valueForKey: может зависеть или не зависеть от специфики реализации класса.Я бы проверил, возвращает ли self.session значение, а valueForKey: - нет.

...