在 NSMutableArray 中分隔对象或字符串?
Separate objects or strings in NSMutableArray?
我是 JSon 的新手,请多多包涵。我正在从 URL 反序列化 JSon,在我尝试分离其中的对象之前,一切都很好。应用程序崩溃,我收到一个我不明白的错误。也许你可以帮我看看我错过了什么。
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if ([data length]>0 && error == nil) {
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (jsonObject != nil && error == nil) {
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
NSDictionary *deserializedDictionary = [[NSDictionary alloc] init];
deserializedDictionary = jsonObject;
NSLog(@"Deserialized Dictionary = %@",deserializedDictionary);
/*
LOG: Deserialized Dictionary = { d = "[{\"unit\":\"P101\",\"price\":36.0000,\"stat\":\"process\",\"type\":\"P12\"},{\"unit\":\"P102\",\"price\":38.0000,\"stat\":\"process\",\"type\":\"P13\"},..}
*/
NSMutableArray *dicts = [[NSMutableArray alloc] init];
dicts = (NSMutableArray *)deserializedDictionary[@"d"];
NSLog(@"Print dicts: %@",dicts);
/*
LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..]
*/
NSLog(@"%@",NSStringFromClass([dicts class]));
//LOG: __NSCFString
NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
for (myDict in dicts)
{
NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"unit"],[myDict objectForKey:@"result"]);
}
}
然后我得到这个错误:
[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7fe97b327790
2016-03-08 11:29:12.946 Poop[49680:5673839] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7fe97b327790'
请帮忙?
查看编辑后的代码:
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if ([data length]>0 && error == nil) {
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (jsonObject != nil && error == nil) {
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
NSDictionary *deserializedDictionary = [[NSDictionary alloc] init];
deserializedDictionary = jsonObject;
NSLog(@"Deserialized Dictionary = %@",deserializedDictionary);
/*
LOG: Deserialized Dictionary = { d = "[{\"unit\":\"P101\",\"price\":36.0000,\"stat\":\"process\",\"type\":\"P12\"},{\"unit\":\"P102\",\"price\":38.0000,\"stat\":\"process\",\"type\":\"P13\"},..}
*/
NSMutableArray *responseArray = [[NSMutableArray alloc] init];
responseArray = deserializedDictionary[@"d"];
NSLog(@"Print responseArray: %@",responseArray);
/*
LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..]
*/
NSLog(@"%@",NSStringFromClass([responseArray class]));
//LOG: __NSCFString
//The correct way of fast enumeration.
for (NSMutableDictionary *myDict in dicts)
{
NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"id"],[myDict objectForKey:@"result"]);
}
}
此外,每次从字典中获取值时,您应该始终检查字典中是否存在键,为此您可以在 HelperClass 中添加此方法,
//Check is key exist in the dictionary
+(BOOL)validateKeyValueForData:(id)dataValue {
if([dataValue isEqual:[NSNull null]] || dataValue == nil)
{
return NO;
}
if([dataValue isKindOfClass:[NSArray class]] || [dataValue isKindOfClass:[NSMutableArray class]])
{
if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue count] <= 0)
{
return NO;
}
}
else
if([dataValue isKindOfClass:[NSDictionary class]] || [dataValue isKindOfClass:[NSMutableDictionary class]])
{
if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue count] <= 0)
{
return NO;
}
}
else if ([dataValue isKindOfClass:[NSString class]] || [dataValue isKindOfClass:[NSMutableString class]])
{
if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue length] <= 0)
{
return NO;
}
}
return YES;
}
并将其用作
for (NSMutableDictionary *myDict in dicts)
{
//This way you make sure that the value for the specified key is exist in the dictionary.
if ([HelperClass validateKeyValueForData:myDict[@"id"]] && [HelperClass validateKeyValueForData:myDict[@"result"]]) {
NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"id"],[myDict objectForKey:@"result"]);
}
}
看起来 dicts
对象以某种方式被实例化为字符串。看一下原始的 NSData
,在它被解析为 JSON 对象之前:
NSString *rawResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Raw data: %@", rawResponse);
如果您设置一个通用断点来捕获所有异常,它可能会在您尝试遍历字典数组的地方停止。您可以通过以下方式做到这一点:
- Select 断点导航器
- 点击左下方的“+”按钮
- Select 'Add Exception Breakpoint...'
- 在弹出的选项菜单中,select Break 'On Catch' 选项
从您的代码和日志中,我可以了解到实际问题出在您的服务器端,因为这些行
NSMutableArray *dicts = [[NSMutableArray alloc] init];
dicts = (NSMutableArray *)deserializedDictionary[@"d"];
NSLog(@"Print dicts: %@",dicts);
/*
LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..]
*/
NSLog(@"%@",NSStringFromClass([dicts class]));
//LOG: __NSCFString
Log 说你的名为 dicts 的变量是 NSCFString 类型而不是 NSMutableArray 和 NSString don在 NSString 类型的对象上没有键和枚举不能 运行。
问题出在您的 API 回复上,return 不正确 JSON。
解决方案是在您的服务器端将字符串更改为 return 数组或字典。
我是 JSon 的新手,请多多包涵。我正在从 URL 反序列化 JSon,在我尝试分离其中的对象之前,一切都很好。应用程序崩溃,我收到一个我不明白的错误。也许你可以帮我看看我错过了什么。
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if ([data length]>0 && error == nil) {
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (jsonObject != nil && error == nil) {
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
NSDictionary *deserializedDictionary = [[NSDictionary alloc] init];
deserializedDictionary = jsonObject;
NSLog(@"Deserialized Dictionary = %@",deserializedDictionary);
/*
LOG: Deserialized Dictionary = { d = "[{\"unit\":\"P101\",\"price\":36.0000,\"stat\":\"process\",\"type\":\"P12\"},{\"unit\":\"P102\",\"price\":38.0000,\"stat\":\"process\",\"type\":\"P13\"},..}
*/
NSMutableArray *dicts = [[NSMutableArray alloc] init];
dicts = (NSMutableArray *)deserializedDictionary[@"d"];
NSLog(@"Print dicts: %@",dicts);
/*
LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..]
*/
NSLog(@"%@",NSStringFromClass([dicts class]));
//LOG: __NSCFString
NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
for (myDict in dicts)
{
NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"unit"],[myDict objectForKey:@"result"]);
}
}
然后我得到这个错误:
[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7fe97b327790 2016-03-08 11:29:12.946 Poop[49680:5673839] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7fe97b327790'
请帮忙?
查看编辑后的代码:
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if ([data length]>0 && error == nil) {
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (jsonObject != nil && error == nil) {
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
NSDictionary *deserializedDictionary = [[NSDictionary alloc] init];
deserializedDictionary = jsonObject;
NSLog(@"Deserialized Dictionary = %@",deserializedDictionary);
/*
LOG: Deserialized Dictionary = { d = "[{\"unit\":\"P101\",\"price\":36.0000,\"stat\":\"process\",\"type\":\"P12\"},{\"unit\":\"P102\",\"price\":38.0000,\"stat\":\"process\",\"type\":\"P13\"},..}
*/
NSMutableArray *responseArray = [[NSMutableArray alloc] init];
responseArray = deserializedDictionary[@"d"];
NSLog(@"Print responseArray: %@",responseArray);
/*
LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..]
*/
NSLog(@"%@",NSStringFromClass([responseArray class]));
//LOG: __NSCFString
//The correct way of fast enumeration.
for (NSMutableDictionary *myDict in dicts)
{
NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"id"],[myDict objectForKey:@"result"]);
}
}
此外,每次从字典中获取值时,您应该始终检查字典中是否存在键,为此您可以在 HelperClass 中添加此方法,
//Check is key exist in the dictionary
+(BOOL)validateKeyValueForData:(id)dataValue {
if([dataValue isEqual:[NSNull null]] || dataValue == nil)
{
return NO;
}
if([dataValue isKindOfClass:[NSArray class]] || [dataValue isKindOfClass:[NSMutableArray class]])
{
if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue count] <= 0)
{
return NO;
}
}
else
if([dataValue isKindOfClass:[NSDictionary class]] || [dataValue isKindOfClass:[NSMutableDictionary class]])
{
if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue count] <= 0)
{
return NO;
}
}
else if ([dataValue isKindOfClass:[NSString class]] || [dataValue isKindOfClass:[NSMutableString class]])
{
if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue length] <= 0)
{
return NO;
}
}
return YES;
}
并将其用作
for (NSMutableDictionary *myDict in dicts)
{
//This way you make sure that the value for the specified key is exist in the dictionary.
if ([HelperClass validateKeyValueForData:myDict[@"id"]] && [HelperClass validateKeyValueForData:myDict[@"result"]]) {
NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"id"],[myDict objectForKey:@"result"]);
}
}
看起来 dicts
对象以某种方式被实例化为字符串。看一下原始的 NSData
,在它被解析为 JSON 对象之前:
NSString *rawResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Raw data: %@", rawResponse);
如果您设置一个通用断点来捕获所有异常,它可能会在您尝试遍历字典数组的地方停止。您可以通过以下方式做到这一点:
- Select 断点导航器
- 点击左下方的“+”按钮
- Select 'Add Exception Breakpoint...'
- 在弹出的选项菜单中,select Break 'On Catch' 选项
从您的代码和日志中,我可以了解到实际问题出在您的服务器端,因为这些行
NSMutableArray *dicts = [[NSMutableArray alloc] init];
dicts = (NSMutableArray *)deserializedDictionary[@"d"];
NSLog(@"Print dicts: %@",dicts);
/*
LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..]
*/
NSLog(@"%@",NSStringFromClass([dicts class]));
//LOG: __NSCFString
Log 说你的名为 dicts 的变量是 NSCFString 类型而不是 NSMutableArray 和 NSString don在 NSString 类型的对象上没有键和枚举不能 运行。
问题出在您的 API 回复上,return 不正确 JSON。
解决方案是在您的服务器端将字符串更改为 return 数组或字典。