使用NSJSONSerialization
解析来自Web服务的JSON响应后,我使用+isKindOfClass:
来确保服务器返回了我期望的数据类型。使用这种方法,我遇到了一些奇怪的行为,我将用一个例子说明。
考虑以下对象:
// Definitions
NSDictionary *son = @{ @"firstname" : @"James", @"lastname" : @"Appleseed" };
NSDictionary *daughter = @{ @"firstname" : @"Susan", @"lastname" : @"Appleseed"};
NSArray *children = @[son, daughter];
NSDictionary *father = @{ @"firstname" : @"John", @"lastname" : @"Appleseed" };
NSDictionary *family = @{@"children" : children, @"father" : father};
NSDictionary *pedigree = @{@"family" : family };
这些对象表示从服务器返回的反序列化JSON。现在,如果我想使用子数组来计算使用NSArray -count
的子项数,我需要确保子对象是NSArray。例如,如果子对象碰巧是一个字符串,而应用程序需要一个数组,它会崩溃,因为字符串没有实现count
方法。请考虑以下代码序列,它实现了所描述的检查:
// First test
id _family = [pedigree objectForKey:@"family"];
if ([_family isKindOfClass:[NSDictionary class]])
{
NSDictionary *_family = (NSDictionary *)_family;
id _children = [_family objectForKey:@"children"];
NSLog(@"Children: %@", _children);
NSLog(@"Children classname: %@", NSStringFromClass(children.class));
if ([_children isKindOfClass:[NSArray class]]) {
NSLog(@"Children is an NSArray");
} else {
NSLog(@"Children is not an NSArray");
}
} else {
NSLog(@"Family is not an NSDictionary");
}
运行此代码后,控制台输出以下内容:
Children: (null)
Children classname: __NSArrayI
Children is not an NSArray
控制台输出似乎非常显着甚至是矛盾的。当孩子的名字是__NSArrayI时,孩子不怎么可能是NSArray?
经过一些调试后,我发现有两种方法可以解决这个问题:
NSDictionary *_family = (NSDictionary *)_family;
_family
不同的名称作为转换变量如何解释这种行为?
答案 0 :(得分:2)
在第
行NSDictionary *_family = (NSDictionary *)_family;
在当前范围中定义新变量_family
,这使得外部变量_family
不可见。如果使用ARC进行编译,则Objective-C指针初始化为nil
。
输出并不矛盾,因为你打印
NSStringFromClass(children.class);
这是children
的类(没有下划线),这是一个数组。但_children
(带下划线)为nil
,因为如上所述,_family
为零。
实际上,如果您需要字典,则不需要进行类型转换。你可以做到
NSDictionary *_family = [pedigree objectForKey:@"family"];
if ([_family isKindOfClass:[NSDictionary class]])
{
NSArray *_children = [_family objectForKey:@"children"];
if ([_children isKindOfClass:[NSArray class]]) {
NSLog(@"Children is an NSArray");
} else {
NSLog(@"Children is not an NSArray");
}
} else {
NSLog(@"Family is not an NSDictionary");
}
答案 1 :(得分:0)
您的变量children
包含一个数组,您的变量_children
为nil
。
这解释了打印NSLog
的第一个(null)
(因为您记录_children
,而不是children
),而是打印{{1}的第二个NSLog
(因为你打印了__NSArrayI
对象的类,而不是nil children
变量的类。
您的第三个_children
表示它不是数组,因为您检查NSLog
而[_children isKindOfClass:...]
是_children
,因此nil
会返回[nil isKindOfClass:...]
}。
因此,要解决您的问题,您必须弄清楚NO
变量为_children
的原因(而nil
变量不是)。
这显然是因为您使用隐藏其父级的children
变量。因此,行_family
显然使用内部NSDictionary *_family = (NSDictionary *)_family;
变量,并且与您编写_family
的行为完全相同:因为此NSDictionary *foo = (NSDictionary *)foo;
为foo
,所以无论你想要什么,它仍然会成为nil
。
为内部nil
变量使用其他名称,以避免第二个_family
变量隐藏外部_family
变量,您的问题就会消失。或者更好,完全删除此行,因为在_family
上调用方法而不进行强制转换是没有问题的(实际上是id
的用途)