Сложная проблема итерации pList и NSDictionary - PullRequest
0 голосов
/ 15 сентября 2010

У меня есть файл pList:

Root - Dictionary
  categories - Array
     item 0 - Dictionary
     item 1 - Dict
     item 2 - Dict

Я загружаю файл так:

-(void) loadCategories
{
    // Loads the categories from the SymbolList.plist file
    NSString *file = [[NSBundle mainBundle] pathForResource:@"SymbolList" ofType:@"plist"];
    NSMutableDictionary *plistSymbolList = [[NSMutableDictionary alloc] initWithContentsOfFile:file];

    categoriesList = [plistSymbolList objectForKey:@"categories"];
    NSLog(@"count is: %d", [categoriesList count]); 

    // Here I am just testing if this method will work
    for(int i = 0; i < [categoriesList count]; i++)
    {
        NSDictionary *dict = [categoriesList objectAtIndex:i];
        NSLog(@"dict count: %d", [dict count]);
    }

    // ideally this is what I'd like to do but doesn't work on device
    for (NSDictionary *dictionary in categoriesList)
    {
        if (dictionary == nil)
            NSLog(@"It's nil.");

        NSLog(@"count: %d", [dictionary count]);

        // get and display the category information
        NSString *catName = [dictionary objectForKey:@"Category Name"];
        NSLog(@"catName is: %@", catName);
        NSString *catImage = [dictionary objectForKey:@"Category Image"]; 
        NSLog(@"catImage is: %@", catImage);

        NSString *fullFile = [NSString stringWithFormat:@"%@.png", catImage];
        NSLog(@"Full file name is: %@", fullFile);

        SymbolButton *categoryButton = [[SymbolButton alloc] initWithName:catName andSymbol:catImage];
        [categoryButton addTarget:self action:@selector(categoryButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [categoryButtonList addObject:categoryButton];
        NSLog(@"Added Button to list");
    }

    [self updateCategories];    

Просто чтобы напомнить, я: 1) загрузка файла для получения моего рута 2) получение моего списка категорий 3) перебирая каждый из них и получая какое-либо значение с помощью objectAtIndex ИЛИ objectForKey

ВСЕ этот код прекрасно работает на эмуляторе и работает без сбоев. Эта функция Умирает, как только я запускаю ее на устройстве:

TestApp[4734:207] count is: 3
TestApp[4734:207] *** -[NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x122d10
TestApp[4734:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x122d10'

Из сообщения об ошибке говорится, что проблема с моими экземплярами. Но почему это работает на сим, а не на устройстве? Все обновлено до последней версии SDK и ОС (не бета) и т. Д.

Если я закомментирую первый цикл for, я получу:

TestApp[4760:207] count is: 3
TestApp[4760:207] *** -[NSCFString count]: unrecognized selector sent to instance 0x120470
TestApp[4760:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFString count]: unrecognized selector sent to instance 0x120470'

Спасибо за любую помощь. Этот убивает меня:)

Ответы [ 3 ]

0 голосов
/ 15 сентября 2010

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

Если внимательно посмотреть сообщение в журнале:

-[NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x120470

вы увидите, что она точно говорит вам, в чем проблема: вы отправляете сообщение -objectAtIndex: экземпляру NSDictionary (NSCFDictionary - это закрытый подкласс NSDictionary).

Ваш код должен компилироваться с предупреждением в этой строке. Небольшой совет: не игнорируйте предупреждения в Objective-C! Обычно они указывают на серьезные проблемы, многие из которых могут быть смертельными во время выполнения.

Проблема во втором цикле аналогична, и опять-таки сообщение журнала сообщает вам все, что вам нужно знать: вы отправляете сообщение -count экземпляру NSString, который, по-видимому, ожидает ваш код NSDictionary.

0 голосов
/ 15 сентября 2010

Оказывается, проблема в том, что файл plist имеет несколько вложенных типов.

У меня был файл plist:

NSDictionary
 - NSArray
   - Item 0
     - Name - String
     - Category - String
     - Image - String
   - Item 1
     - Name - String
     - Category - String
     - Image - String
   - Item 2
     - Name - String
     - Category - String
     - Image - String

Эмулятор обрабатывал эту тонкую загрузку, как я упоминалвыше.Однако устройство просто не будет правильно читать элементы.

Я изменил свой plist-файл на:

  NSArray
   - Item 0
     - Name - String
     - Category - String
     - Image - String
   - Item 1
     - Name - String
     - Category - String
     - Image - String
   - Item 2
     - Name - String
     - Category - String
     - Image - String

Корнем является массив, и он продолжает работать как обычно с этого момента.

Я подумал, что, может быть, я читал объект, когда он должен был быть значением, но это не так.Однако информация об отладке указывает на это.Это все еще кажется странным, но теперь оно отлично работает как в эмуляторе, так и на устройстве.

Надеюсь, это поможет любому с этой же проблемой.

0 голосов
/ 15 сентября 2010

Три вещи: во-первых, я думаю, что вы должны использовать valueForkey: не objectForKey: я предполагаю, что у вас есть String в вашем словаре.Примерно так:

NSString *catName = [dict valueForKey:@"Category Name"];

Второе: почему бы не переместить все из NSString * catName = [словарь objectForKey: @ "Имя категории"];в первый цикл for и выполните NSString * catName = [dict objectForKey: @ "Category Name"];вместо?Должны сделать ту же работу. Итак, вы бы получили что-то вроде этого:

for(int i = 0; i < [categoriesList count]; i++)
{
NSDictionary *dict = [categoriesList objectAtIndex:i];
NSLog(@"dict count: %d", [dict count]);
NSString *catName = [dict objectForKey:@"Category Name"];
NSLog(@"catName is: %@", catName);
NSString *catImage = [dict objectForKey:@"Category Image"];

}

В-третьих: я не думаю, что [словарь подсчета] сработает, попробуйте убрать это.

Надеюсь, это поможет

...