Базовые данные не могут разрешать ошибки, когда объект имеет атрибут «описание»? - PullRequest
3 голосов
/ 30 января 2010

Код:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"A"
                                          inManagedObjectContext:moc];
[fetchRequest setEntity:entity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"somePredicate", someObject];
[fetchRequest setPredicate:predicate];

frc = [[NSFetchedResultsController alloc]
       initWithFetchRequest:fetchRequest
       managedObjectContext:moc
       sectionNameKeyPath:@"recency"
       cacheName:@"frc"];
[fetchRequest release];

frc.delegate = self;

NSError *error;
BOOL success = [frc performFetch:&error];
if (!success) {
    NSLog(@"error: %@", error);
}

for (A *a in [frc fetchedObjects]) {        
    [someMutableArray addObject:a.b];
    [someMutableArray addObject:a];
}

Модель данных:

A и B являются субъектами. A имеет обязательное отношение «один к одному» с B. B имеет обратное необязательное отношение ко многим к A.

Выше на английском:

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

Теперь, позже, я попытаюсь сделать это:

id object = [someMutableArray objectAtIndex:someIndex];
NSLog(@"%@", object);

if ([object isMemberOfClass:[B class]]) {
    someVar = object.propertyFromB; // problem
} else if ([object isMemberOfClass:[A class]]) {
    someVar = object.propertyFromA;
}

Вопрос / проблема: строка, обозначенная «проблема», вылетает. (РЕДАКТИРОВАТЬ: см. Ниже для разрешения, но все еще хотел бы объяснение.)

Вызов NSLog выше дает:

2010-01-30 14:47:14.433 app[22618:20b] <B: 0xf7f750> (entity: B; id: 0xf7ba70 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/B/p4> ; data: <fault>)
2010-01-30 14:47:14.438 app[22618:20b] <A: 0xf7e360> (entity: A; id: 0xf35820 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/A/p6> ; data: {
    prop1 = value1;
    prop2 = value2;
    ... etc ...
})

Т.е. по проблемной строке, если объект был типа A, он был поврежден и доступен в памяти, но если это B, это ошибка.

Насколько я понимаю, строка "проблема" должна вызвать ошибку и извлечь данные из хранилища, но этого не происходит. Я хотел бы понять / отладить почему. Я попытался вставить вызовы willAccessKey / didAccessKey вокруг этого. Я также попытался установить setRelationshipKeyPathsForPrefetching: "b" в запросе на выборку. Ни один не работал.

Моя гипотеза состоит в том, что, поскольку я несколько злоупотребляю результатами NSFetchedRequestController, неисправный механизм путается по пути и не выдает ошибку, когда он должен. Так что я думаю, что грубым способом было бы создать новый запрос на ручную выборку, чтобы получить связанный объект B в нужное время. Но есть ли лучший способ?

EDIT:

Проблема состояла в том, что у объекта B было свойство "описание", которое я определил, но это вступает в противоречие со встроенным именем NSObject. Xcode всегда давал мне предупреждения, но я игнорировал их, потому что я думал, что внутреннее свойство / метод "description" используется только для выгрузки строк в консоль и т. П., А не для внутренней обработки.

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

Я не понимаю, однако, что происходит. Использует ли Core Data метод «описания» объектов для некоторого внутреннего самоанализа?

Ответы [ 3 ]

6 голосов
/ 31 января 2010

С Руководство по программированию основных данных

Вам не рекомендуется переопределять описание - если этот метод вызывает ошибку во время операции отладки, результаты могут быть непредсказуемыми - и initWithEntity: insertIntoManagedObjectContext :. Обычно вы не должны переопределять методы кодирования значения ключа, такие как valueForKey: и setValue: forKeyPath:.

-description - это метод в NSObject, который возвращает строковое представление вашего объекта. В строке NSLog(@"%@", object), -description используется для получения строки, которую вы видите в консоли. Кодирование ключ-значение закончится использованием метода для получения свойства для атрибута description. Это приводит к путанице с базовыми данными.

Руководство по программированию щедро, когда в нем написано "обескуражен". Они действительно означают «Да, это сломает ваши вещи».

Эта ссылка также содержит хороший список других методов, которые могут сломать ваши данные, если вы их переопределите.

0 голосов
/ 15 января 2013

Для пользовательских описаний вы можете переопределить -(NSString *)debugDescription из протокола NSObject. Из документа Apple:

NSObject реализует этот метод, вызывая метод описания. Таким образом, по умолчанию описание отладки объекта совпадает с описание. Тем не менее, вы можете переопределить debugDescription, если вы хотите отделить их.

0 голосов
/ 31 января 2010

вы должны рассматривать описание как зарезервированное слово. Это проблема, с которой вы столкнулись. Вы должны были получить предупреждение, когда пытались получить свойство с именем description.

...