【问题标题】:Separate objects or strings in NSMutableArray?在 NSMutableArray 中分隔对象或字符串?
【发布时间】:2016-06-22 06:22:41
【问题描述】:

我是 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:]:无法识别的选择器发送到实例 0x7fe97b327790 2016-03-08 11:29:12.946 Poop[49680:5673839] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[__NSCFString countByEnumeratingWithState:objects:count:]:无法识别的选择器发送到实例 0x7fe97b327790”

请帮忙?

【问题讨论】:

  • 某处,您说您的对象是NSDictionaryNSArray(不确定是哪一个),实际上它是NSString,这会导致“无法识别的选择器发送到实例”。似乎dicts类是NSString而不是NSMutableArray。还有一些 alloc/init 完全错误...
  • 它到底在哪里崩溃,在哪一行?还要更改这一行 - dicts = (NSMutableArray *)deserializedDictionary[@"d"]; to dicts = deserializedDictionary[@"d"];
  • 请发布您的示例数组,以便我可以根据其结构检查您的代码
  • @BharatModi 尝试输入for 时崩溃。马上改,谢谢! @PradheepNarendranP 原始数组看起来像我的代码中的第一个 LOG,但它太长无法发布,这就是为什么我只显示前 2 个单元。
  • 这段代码有很多问题......你应该考虑从小得多的东西开始。

标签: ios objective-c json nsjsonserialization


【解决方案1】:

查看修改后的代码:

[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"]);
   }

}

【讨论】:

  • 谢谢!我做了一些你建议的改变,它与另一个 JSON 一起工作,结果我使用的那个格式错误:/
【解决方案2】:

看起来dicts 对象以某种方式被实例化为字符串。看看原始的NSData,在它被解析成 JSON 对象之前:

NSString *rawResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Raw data: %@", rawResponse);

如果您设置一个通用断点来捕获所有异常,它可能会在您尝试遍历您的 dicts 数组时停止。你可以这样做:

  1. 选择断点导航器
  2. 点击左下角的“+”按钮
  3. 选择“添加异常断点...”
  4. 在弹出的选项菜单中,选择 Break 'On Catch' 选项

【讨论】:

    【解决方案3】:

    从您的代码和日志中,我可以从这些行中了解到实际问题出在您的服务器端

    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
    

    日志说您名为 dicts 的变量属于 NSCFString 类型而不是 NSMutableArray 并且 NSString 没有键并且枚举无法在 NSString 对象类型。

    问题在于您的 API 响应,它没有返回正确的 JSON。

    解决方案是在您的服务器端更改以返回数组或字典而不是字符串。

    【讨论】:

    • 事实证明,正如您所说,我收到的内容格式错误。我用其他来源(api.github.com/users)尝试了我的代码并且它有效。我已经要求服务提供商修改他们的 JSON。感谢您提供一些启示!
    猜你喜欢
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多