Я пишу приложение для словаря и пытаюсь импортировать необработанные данные из строк, по одной строке на слово.Среди прочего, необработанные входные строки содержат названия частей речи, к которым принадлежит соответствующее слово.В моей модели данных у меня есть отдельная сущность для Word
s и PartOfSpeech
, и я хочу создать одну сущность типа PartOfSpeech
для каждой уникальной части речи, которая может присутствовать во входных строках, и установить отношения изWord
с соответствующих пар речи.У сущности PartOfSpeech
есть только один атрибут, name
и отношение один-ко-многим с Word
: ![enter image description here](https://i.stack.imgur.com/s7zJl.png)
Моя первая реализация получения уникальных PartOfSpeech
сущностей, включающих их кеширование визменяемый массив и его фильтрация каждый раз с помощью предиката.Это работало, но было медленно.Я решил немного ускорить его, кэшируя PartsOfSpeech в NSDictionary, и теперь, когда я пытаюсь сохранить хранилище данных после импорта, я получаю сообщение об ошибке «Невозможно сохранить объекты со ссылками вне их собственных хранилищ».Похоже, проблема в словаре, но как я могу ее решить?
Вот код, который сработал: (в обоих фрагментах managedObjectContext
- это ivar, а метод processStringsInBackground:
работает на фонес использованием метода performSelectorInBackground:withObject:
)
- (void) processStringsInBackground:(NSFetchRequest *)wordStringsReq {
NSError *err = NULL;
NSFetchRequest *req = [[NSFetchRequest alloc] init];
[req setEntity:[NSEntityDescription entityForName:@"PartOfSpeech" inManagedObjectContext:managedObjectContext]];
err = NULL;
NSMutableArray *selectedPartsOfSpeech = [[managedObjectContext executeFetchRequest:req error:&err] mutableCopy];
NSPredicate *p = [NSPredicate predicateWithFormat:@"name like[c] $name"];
// NSPredicate *formNamePredicate = [NSPredicate predicateWithFormat:<#(NSString *)predicateFormat#>]
...
for (int i = 0; i < count; i++){
...
currentPos = [self uniqueEntityWithName:@"PartOfSpeech" usingMutableArray:selectedPartsOfSpeech predicate:p andDictionary:[NSDictionary dictionaryWithObject:partOfSpeech forKey:@"name"]];
...
}
}
- (NSManagedObject *) uniqueEntityWithName:(NSString *) entityName usingMutableArray:(NSMutableArray *)objects predicate:(NSPredicate *)aPredicate andDictionary:(NSDictionary *) params {
NSPredicate *p = [aPredicate predicateWithSubstitutionVariables:params];
NSArray *filteredArray = [objects filteredArrayUsingPredicate:p];
if ([filteredArray count] > 0) {
return [filteredArray objectAtIndex:0];
}
NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:managedObjectContext];
NSArray *dicKeys = [params allKeys];
for (NSString *key in dicKeys) {
[newObject willChangeValueForKey:key];
[newObject setPrimitiveValue:[params valueForKey:key] forKey:key];
[newObject didChangeValueForKey:key];
}
[objects addObject:newObject];
return newObject;
}
И здесь то же самое, но с кэшированием с использованием NSMutableDictionary, который впоследствии не удается сохранить:
- (void) processStringsInBackground:(NSFetchRequest *)wordStringsReq {
NSError *err = NULL;
[req setEntity:[NSEntityDescription entityForName:@"PartOfSpeech" inManagedObjectContext:managedObjectContext]];
NSArray *selectedPartsOfSpeech = [managedObjectContext executeFetchRequest:req error:&err];
NSMutableDictionary *partsOfSpeechChache = [[NSMutableDictionary alloc] init];
for (PartOfSpeech *pos in selectedPartsOfSpeech) {
[partsOfSpeechChache setObject:pos forKey:pos.name];
}
...
for (int i = 0; i < count; i++){
...
currentPos = [self uniqueEntity:@"PartOfSpeech" withName:partOfSpeech usingDictionary:partsOfSpeechChache];
...
}
}
- (NSManagedObject *)uniqueEntity:(NSString *) entityName withName:(NSString *) name usingDictionary:(NSMutableDictionary *) dic {
NSManagedObject *pos = [dic objectForKey:name];
if (pos != nil) {
return pos;
}
NSManagedObject *newPos = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:managedObjectContext];
[newPos willChangeValueForKey:@"name"];
[newPos setPrimitiveValue:name forKey:@"name"];
[newPos didChangeValueForKey:@"name"];
[dic setObject:newPos forKey:name];
return newPos;
}
Не могли бы вы помочь мне найтипроблема?
С уважением, Тимофей.