如何从分层.plist中获取值?

时间:2015-04-20 16:30:07

标签: ios dictionary tree plist

  

我已经查看Parse Plist (NSString) into NSDictionary并认为它是不重复,因为该问题及其答案并未解决我的疑虑。


我在文件系统中有一个.plist文件,结构如下:

Root > My App > Side Panel > Items > Price

.plist文件的源代码如下所示:

{
    "My App" = {
        "Side Panel" = {
            Items = {
                Price = "#123ABC";
            };
        };
    };
}

我知道如何在Root中获取这样的项目:

[[NSBundle mainBundle] pathForResource:@"filename" ofType:@"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSString value = [dict objectForKey:@"key"]);

但是,如果结构像我一样,有分层词典怎么办? 如何获得Price的价值?

我想在一种方法中完成所有这些,理想情况如下:

调用

NSString *hexString = [self getColorForKey:@"My App.Side Panel.Items.Price"];

定义

- (NSString *) getColorForKey: (NSString *)key
{
    NSArray *path = [key componentsSeparatedByString:@"."];
    NSDictionary *colors = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Colors" ofType:@"plist"]];
    NSString *color = @"#FFFFFF"; // white is our backup

    // What do I put here to get the color?

    return color;
}

2 个答案:

答案 0 :(得分:0)

以下是适用于我的解决方案:

+ (NSString*) getHexColorForKey:(NSString*)key
{
    NSArray *path = [key componentsSeparatedByString:@"."];
    NSDictionary *colors = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Colors" ofType:@"plist"]];
    NSString *color = @"#FFFFFF";
    for (NSString *location in path) {
        NSObject *subdict = colors[location];
        if ([subdict isKindOfClass:[NSString class]])
        {
            color = (NSString*)subdict;
            break;
        }
        else if ([subdict isKindOfClass:[NSDictionary class]])
        {
            colors = (NSDictionary*)subdict; // if it's a dictinoary, our color may be inside it
        }
        else
        {
            [SilverLog level:SilverLogLevelError message:@"Unexpected type of dictinoary entry: %@", [subdict class]];
            return color;
        }
    }
    return color;
}

其中key是与NSString匹配的/^[^.]+(\.[^.]+)*$/,这意味着它看起来像我的目标@"My App.Side Panel.Items.Price"

答案 1 :(得分:0)

是的,我理解你想要完成的事情;谢谢你的澄清。但是我会补充一点,我写的资源和建议确实提供了解决问题的必要信息。

也就是说,以下内容获取您的字典:

NSURL *plistURL = [[NSBundle mainBundle] URLForResource:@"Info" withExtension:@"plist"];
NSData *plistData = [NSData dataWithContentsOfURL:plistURL];
NSDictionary *tieredPlistData = [NSPropertyListSerialization propertyListWithData:plistData 
                                                                          options:kCFPropertyListImmutable 
                                                                           format:NULL 
                                                                            error:nil];

然后,如果我们对Items

中包含的信息感兴趣
NSDictionary *allItemsDictionary = tieredPlistData[@"My App"][@"Side Panel"][@"Items"];

假设Items将包含许多对象,您可以使用

NSArray *keys = [allItems allKeys];
for(NSString *key in keys){
    NSString *colorValue = allItemsDictionary[key];
    // do something with said color value and key
}

或者,如果您需要一个值,那么只需引用该键

NSString *colorForPriceText = allItemsDictionary[@"Price"];

但有一些提示:

  • 通常认为将频繁访问的值保留在代码中而不是在运行时加载的plist /文件更好。
  • 也就是说,您不会使用与查询特定值相同的方法从NSBundle加载您的调用。在您的示例中,每次需要颜色时,最终都会重新访问NSBundle并堆积在不需要的内存分配上。一种方法是将plist加载到iVar NSDictionary中,然后NSDictionary将由另一种方法单独使用。