挑战pList迭代和NSDictionary问题

时间:2010-09-15 14:32:37

标签: iphone nsarray plist nsdictionary

我有一个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)加载文件以获取我的root 2)获取我的类别列表 3)循环遍历每个并使用objectAtIndex或objectForKey

获取一些值

所有这些代码在模拟器上运行良好,运行完美,没有崩溃。 这个功能在我在设备上运行时立即进行DIES:

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'

从错误消息中可以看出我的实例存在问题。但为什么这会在SIM卡而不是设备上运行?一切都更新到最新的SDK和操作系统版本(非beta)等。

如果我注释掉第一个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 :(得分:0)

三件事: 首先我认为你应该使用valueForkey:而不是objectForKey:我假设你的字典中有字符串。像这样:

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

第二:为什么不从NSString中移动所有内容* catName = [dictionary objectForKey:@“Category Name”];进入第一个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"];

}

第三:我不认为[字典计数]会起作用,试着把它拿出来。

希望这有帮助

答案 1 :(得分:0)

您可能正在模拟器上阅读不同版本的plist文件,而不是当前手机上的文件。第一个循环中的问题是显然模拟器上的plist中存储的categoriesList是一个数组,而手机上的-[NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x120470 是一个字典。

如果仔细查看日志消息:

-objectAtIndex:

你会看到它确切地告诉你问题是什么:你正在向NSDictionary的一个实例发送NSCFDictionary消息(NSDictionary-count的私有子类)

您的代码应该在该行上发出警告进行编译。一点建议:不要忽略Objective-C中的警告!它们通常表示严重的问题,其中许多可能是运行时致命的。

第二个循环中的问题是类似的,同样,日志消息告诉您需要知道的一切:您正在向NSString的实例发送{{1}}消息,您的代码显然期待这一消息成为NSDictionary。

答案 2 :(得分:0)

事实证明,问题在于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

root是一个数组,从这一点开始,它会继续正常运行。

我想也许我正在阅读一个物体,它应该是一个值,但事实并非如此。但是,调试信息指向此。这看起来仍然很奇怪,但它现在在模拟器和设备上都能很好地工作。

我希望这可以帮助任何有同样问题的人。