Назначение извлеченного NSManagedObject свойству

Этот вопрос может показаться длинным, но я уверен, что для экспертов Core-Data он относительно прост. Показ конфигурации сделал этот вопрос длинным. Спасибо!

В CoreData у меня есть сущность User и подкласс NSManagedObject (User.h/.m), созданный из этой сущности. Не уверен, что это актуально, но я использую удаленную базу данных со Stackmob.

Вот как выглядит мой запрос на выборку в Review.m:

Запрос на получение:

-(NSArray *)fetchRequest
{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

   //Please Note the line below:
    [fetchRequest setReturnsObjectsAsFaults:NO];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"username == %@", self.usernameField.text];
    [fetchRequest setPredicate:predicate];

    NSError *error = nil;
    NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];

    return fetchedObjects;
}


if (fetchedObjects.count>=1)
        {
            NSLog(@"Number of Objects Returned %i", fetchedObjects.count);
            NSManagedObject *fetchedObject = [fetchedObjects objectAtIndex:0];
        }

Вот журнал:

2013-08-18 10:26:25.082 Time[995:c07] Number of Objects Returned 1
2013-08-18 10:26:25.082 Time[995:c07] User Object: <User: 0xe07b260> (entity: User; id: 0xa65ab70 <x-coredata://392983AD-D649-4D68-A93F-D86109BC009C-995-000004B584F1BB06/User/piphone5> ; data: <fault>)

Несколько недель назад я успешно создал пользовательский объект со следующим:

User *newUser = [[User alloc] initIntoManagedObjectContext:self.managedObjectContext];

[newUser setValue:self.usernameField.text forKey:[newUser primaryKeyField]];
[newUser setValue:self.emailAddressField.text forKey:@"email"];

[newUser setPassword:self.passwordField.text];
[newUser setValue:self.gender forKey:@"gender"];

[self.managedObjectContext saveOnSuccess:^{

    [self.client loginWithUsername:self.usernameField.text password:self.passwordField.text onSuccess:^(NSDictionary *results) {

        NSLog(@"Login Success %@",results);

    } onFailure:^(NSError *error) {
        NSLog(@"Login Fail: %@",error);
    }];

Вот что я хотел бы сделать в Review.m:

@interface Review()
@property (strong, nonatomic) User *user;
@end
@sythesize = user;
....
if (fetchedObjects.count>=1)
{
    NSLog(@"Number of Objects Returned %i", fetchedObjects.count);
    NSManagedObject *fetchedObject = [fetchedObjects objectAtIndex:0];
    NSLog(@"fetchObject Object %@", fetchedObject);

    //Addition
    user = (User*)(fetchedObject);
    NSLog(@"User %@", user);
}

Вот журнал:

2013-08-18 11:07:13.313 Time[1177:c07] Number of Objects Returned 1
2013-08-18 11:07:13.314 Time[1177:c07] fetchObject Object <User: 0xa532cc0> (entity: User; id: 0xb426de0 <x-coredata://3336122B-7117-4D92-B0A1-DDBAF80DDBF7-1177-000006EEE046E326/User/piphone5> ; data: <fault>)
2013-08-18 11:07:13.314 Time[1177:c07] User <User: 0xa532cc0> (entity: User; id: 0xb426de0 <x-coredata://3336122B-7117-4D92-B0A1-DDBAF80DDBF7-1177-000006EEE046E326/User/piphone5> ; data: <fault>)

Почему это не работает? Пользователь по-прежнему отображается как Fault? У меня есть следующая строка в запросе на выборку: [fetchRequest setReturnsObjectsAsFaults:NO];

Вот причина, по которой мне нужно это сделать:

Notification *notificationObject = [NSEntityDescription insertNewObjectForEntityForName:@"Notification" inManagedObjectContext:self.managedObjectContext];

[notificationObject setValue:[NSNumber numberWithInt:1] forKey:@"appType"];
[notificationObject setValue:[notificationObject assignObjectId] forKey:[notificationObject primaryKeyField]];

NSError *error = nil;
if (![self.managedObjectContext saveAndWait:&error])
{
      NSLog(@"There was an error");
}
     else
{
     NSLog(@"Notification Object Created");
}
        //I need to Add the fetchedObject as UsersObject (which is a relationship) 
        [notificationObject addUsersObject:user];
        [self.managedObjectContext saveOnSuccess:^{ ....

Вот моя настройка CoreData: введите здесь описание изображения

Почему это не работает? Пользователь по-прежнему отображается как Fault? У меня есть следующая строка в запросе на выборку: [fetchRequest setReturnsObjectsAsFaults:NO];


person user1107173    schedule 18.08.2013    source источник
comment
Ошибка Core Data — это объект-заполнитель и вообще не ошибка. При необходимости данные извлекаются из базы данных. Попробуйте войти, например. user.email, должно работать.   -  person Martin R    schedule 18.08.2013
comment
Да, это единственный способ, которым я могу вызвать срабатывание ошибки, получив доступ к одному из ее свойств. Я надеялся [fetchRequest setReturnsObjectsAsFaults:NO]; будет работать.   -  person user1107173    schedule 18.08.2013
comment
К сожалению, я пропустил эту часть вашего вопроса, извините. Но я сделал небольшой тест с [fetchRequest setReturnsObjectsAsFaults:NO], и он сработал, как и ожидалось. - Для добавления объекта «Пользователь» в качестве связанного объекта с объектом «Уведомление» также не должно иметь значения, является ли добавленный объект ошибкой или нет.   -  person Martin R    schedule 18.08.2013


Ответы (2)


Это ограничение StackMob. В https://developer.stackmob.com/ios-sdk/core-data-guide явно указано, что returnObjectsAsFaults / setReturnObjectsAsFaults: (пока) не поддерживается.

person Martin R    schedule 18.08.2013
comment
Хороший улов! Я бы этого не знал. - person Mundi; 19.08.2013

Управляемый объект, отображаемый в журнале как ошибка, в порядке. Используйте его или получите доступ к его свойствам, и Core Data заполнит ошибки наиболее эффективным способом с минимальной нагрузкой на ресурсы.

Эта последняя часть важна, потому что это причина, по которой вы действительно не хотите менять ошибочное поведение Core Data. Необходимость отправки уведомления этого не меняет.

Кроме того, ссылаясь на раздел об ошибках в Руководство по программированию основных данных:

Пакетная ошибка

Вы можете выполнить пакетную ошибку коллекции объектов, выполнив запрос на выборку с помощью предиката с оператором IN, как показано в следующем примере. [...]

NSArray *array = [NSArray arrayWithObjects:fault1, fault2, ..., nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self IN %@", array];

В OS X v10.5 и более поздних версиях при создании запроса на выборку вы можете использовать метод NSFetchRequest setReturnsObjectsAsFaults:, чтобы гарантировать, что управляемые объекты не возвращаются как ошибки.

Итак, вы видите, специальный ярлык запроса на выборку доступен только для OS X. Прочтите приведенный выше источник, чтобы проверить альтернативу, предварительную выборку.

person Mundi    schedule 18.08.2013
comment
Но остается вопрос, почему объекты возвращаются как ошибки, даже если [fetchRequest setReturnsObjectsAsFaults:NO] задано явно. По крайней мере, так утверждает ОП. - person Martin R; 19.08.2013
comment
setReturnsObjectsAsFaults: также доступен на iOS 3.0 или более поздней версии. - person Martin R; 19.08.2013
comment
Не согласно вышеуказанному источнику. - person Mundi; 19.08.2013
comment
Я протестировал его (с симулятором iOS), и [fetchRequest setReturnsObjectsAsFaults:NO] работает. К сожалению, руководство по программированию основных данных не очень актуально. - person Martin R; 19.08.2013