valueForKeyPath的奇怪问题:@“@ max.totalSteps”,这是iOS平台代码中的这个错误吗?

时间:2014-10-11 02:54:33

标签: ios iphone json

我花了几个小时来调试这个问题,因此如果您有专家建议/线索,可以发布这个问题。

以下是问题所在的代码:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"plot" ofType:@"json"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSInteger minSteps = [dict[@"steps"] valueForKeyPath:@"@min.totalSteps"];
NSInteger maxSteps = [dict[@"steps"] valueForKeyPath:@"@max.totalSteps"];
NSLog(@"Min Steps = %@", minSteps);
NSLog(@"Max Steps = %@", maxSteps);

下面提供的JSON内容,上面的代码预计会产生 minSteps 为“ 0 ”(),以及 maxSteps 为“ 710 ”。

然而,上面的代码产生了以下内容。

最小步数= 0  最高步数= 90

为什么发现最大值为“90”​​?

有什么线索值得赞赏吗?

plot.json文件的内容:

{
    steps =     (
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 75;
        },
                {
            totalSteps = 184;
        },
                {
            totalSteps = 113;
        },
                {
            totalSteps = 90;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 11;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 386;
        },
                {
            totalSteps = 282;
        },
                {
            totalSteps = 22;
        },
                {
            totalSteps = 42;
        },
                {
            totalSteps = 710;
        },
                {
            totalSteps = 200;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 111;
        },
                {
            totalSteps = 12;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 49;
        },
                {
            totalSteps = 67;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 104;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 55;
        }
    );
}

为每个请求提供调试器输出: PS:很抱歉JSON的长度有重复,因为它接近实时数据。

(lldb) po dict
{
    steps =     (
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 75;
        },
                {
            totalSteps = 184;
        },
                {
            totalSteps = 113;
        },
                {
            totalSteps = 90;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 11;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 386;
        },
                {
            totalSteps = 282;
        },
                {
            totalSteps = 22;
        },
                {
            totalSteps = 42;
        },
                {
            totalSteps = 710;
        },
                {
            totalSteps = 200;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 111;
        },
                {
            totalSteps = 12;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 49;
        },
                {
            totalSteps = 67;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 104;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 0;
        },
                {
            totalSteps = 55;
        }
    );
}

(lldb) po [dict[@"steps"] valueForKeyPath:@"@min.totalSteps"];
0

(lldb) po [dict[@"steps"] valueForKeyPath:@"@max.totalSteps"];
90

(lldb) po minSteps
0

(lldb) po maxSteps
90

(lldb) 

@Matt,再次感谢。我也找到了有效的解决方案: 为了其他好处,我提供了运行良好的代码。

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"plot" ofType:@"json"];
NSError *jsonParsingError = nil;
NSMutableDictionary *responseObject = [NSJSONSerialization
                                       JSONObjectWithData:[NSData dataWithContentsOfFile:filePath]
                                       options:NSJSONReadingMutableContainers error:&jsonParsingError];
NSInteger minSteps = [dict[@"steps"] valueForKeyPath:@"@min.totalSteps"];
NSInteger maxSteps = [dict[@"steps"] valueForKeyPath:@"@max.totalSteps"];
NSLog(@"Min Steps = %@", minSteps);
NSLog(@"Max Steps = %@", maxSteps);

但请注意,如果JSON结构不太正确,只需要很少的修改,就可以被NSJSONSerialization解析器接受。

以下是具有可接受格式的修改文件:

{
    “steps” :     (
                {
            “totalSteps” : 0,
        },
...

如果你看到这样的问题:

(lldb) po jsonParsingError
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (No string key for value in object around character 6.) UserInfo=0x109875d50 {NSDebugDescription=No string key for value in object around character 6.}

请检查JSON格式的有效性。并确保您的文件不是RTF格式等...

1 个答案:

答案 0 :(得分:1)

这是因为当您的文件变成字典时,steps最终会变成一个字典数组,其中totalSteps是键,值是字符串 。从字符串的角度来看,"90"是最大的(因为它以字母 "9"开头,后来出现在"字母表中#34}其他数字;数字,如字符,从"0""9")。

的原因是你正在以 .plist 的形式阅读文件 - 你根本就没有把它作为JSON阅读。 [NSDictionary dictionaryWithContentsOfFile:filePath]将文件解释为 .plist 。如果您希望它被解释为JSON,请将其作为NSData读取,然后使用JSON方法(NSJSONSerialization)将其转换为Cocoa对象。

我们不能想象该文件只会因为其名称以" json"结尾而被读取为JSON。 dictionaryWithContentsOfFile:只做一件事:它将文件读作.plist。您的文件只是在门口,因为它可以被理解为一个旧式的属性列表":请参阅https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/PropertyLists/OldStylePlists/OldStylePLists.html#//apple_ref/doc/uid/20001012-BBCBDBJE。旧式房产清单中没有数字;只有字符串。在某种程度上,你是不吉利的;如果尝试将文件作为属性列表读取失败,那对你来说会更好!但遗憾的是,NSDictionary能够将其解释为旧式的财产清单。