Чтение plist в основные данные - NSDictionary в NSDictionary - PullRequest
4 голосов
/ 19 июля 2011

У меня есть список значений, которые я хочу прочитать в Core Data.Я могу читать в «верхнем уровне», но наряду со строками и числами, каждый элемент также содержит словари.У меня проблемы с получением правильного синтаксиса для чтения.

Garden и Plant - мои 2 основных объекта данных.И Сад, и Растение - это словари NS, содержащие данные о себе.Сады могут содержать много растений, а определенные растения могут быть во многих садах, так что между многими существует множество отношений.

Это много работает:

Я использую списки садов, чтобы заполнить своиБазовая база данных на firstRun, вызываемая из завершенного запуска приложения, выглядит так:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  
    if (![defaults objectForKey:@"firstRun"])
    {
        [defaults setObject:[NSDate date] forKey:@"firstRun"];
        [[NSUserDefaults standardUserDefaults] synchronize];
        [self loadGardenDataFromPlistDictionary]; 
    }

Это работает.И так же первый уровень загрузки различных значений plist в основные данные.Но у меня возникают проблемы с загрузкой данных, которые содержатся в словаре «растений», который находится внутри словаря «сада» ... глубиной 2 уровня.Другими словами, имя, детали и примечания загружаются ... а растения нет.Вот мой код:

 -(void) loadGardenDataFromPlistDictionary{
// build path to plist; check Documents first, then Bundle.
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"defaultGardenDictionary.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) 
{
    // if not in documents, get property list from main bundle
    plistPath = [[NSBundle mainBundle] pathForResource:@"defaultGardenDictionary" ofType:@"plist"];
}

// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;

// convert static property list into dictionary object
NSDictionary *plistDictionary = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!plistDictionary) 
{
    NSLog(@"Error reading plist: %@, format: %d", errorDesc, format);
}


NSManagedObjectContext *context = self.managedObjectContext;

[plistDictionary enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id key, id object, BOOL *stop) {
    NSManagedObject *gardenManObj = [NSEntityDescription insertNewObjectForEntityForName:@"Garden" inManagedObjectContext:context];

    [gardenManObj setValue:[thisGardenDictionary objectForKey:@"name"] forKey:@"name"];
    [gardenManObj setValue:[thisGardenDictionary objectForKey:@"detail"] forKey:@"detail"];
    [gardenManObj setValue:[thisGardenDictionary objectForKey:@"notes"] forKey:@"notes"];
    [gardenManObj setValue:[thisGardenDictionary objectForKey:@"rating"] forKey:@"rating"];

    NSDictionary *thisGardenPlantsDictionary = [thisGardenDictionary objectForKey:@"plants"];
    NSLog(@"thisGardenPlantsDictionary contains %i dictionaries.", [thisGardenPlantsDictionary count]);
    //The trace statement above shows the correct number of plants in each garden dictionary. oooh... so tantalizingly close!

    //However, the next item is the dictionary of plants in this garden. It comes up blank. 
    //I don't understand the syntax to load that dictionary of plants into its corresponding dictionary of plants within a garden in core data. 

    //I deleted most of the things I've tried and failed with so far. Here's my last attempt:

    // the obvious and parallel:
    [gardenManObj setValue:[thisGardenDictionary objectForKey:@"plants"] forKey:@"plants"];
        //did not work; xCode compiler objected to "incompatible pointer types."

    //the compiler seemed to want an NSSet, so I tried:
    NSSet *thisGardenPlantsSet = [thisGardenDictionary mutableSetValueForKey:@"steps"];
        NSLog(@"thisGardenPlantsSet contains %i sets.", [thisGardenPlantsSet count]);
    [gardenManObj setValue:thisGardenPlantsSet forKey:@"steps"];
    //the compiler was fooled, but the setValue crashed at runtime.
 }];   

}

Что мне не хватает?

1 Ответ

2 голосов
/ 19 июля 2011

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

Вам необходимо добавить что-то вроде:

[gardenManObj setValue:[thisGardenDictionary objectForKey:@"rating"] forKey:@"rating"];

NSDictionary *thisGardenPlantsDictionary = [thisGardenDictionary objectForKey:@"plants"];
NSLog(@"thisGardenPlantsDictionary contains %i dictionaries.", [thisGardenPlantsDictionary count]);
NSManagedObject *plantMO;
for (Plant *eachPlant in thisGardenPlantsDictionary) {
  plantMO=[NSEntityDescription insertNewObjectForEntityForName:@"Plant" inManagedObjectContext:context];
  [plantMO setValue:[eachPlant valueForKey:@"someValue" forKey:@"someKey"]];
   //... repeat for all attributes
  [plantMO setValue:gardenManObj forKey:@"gardent"];
}

..., которое создаст необходимые Plant объекты и установит связь с правильным Garden объектом.

...