使用 allKeys 时应用程序崩溃,是因为只有一个对象吗?

发布于 2024-12-25 12:22:39 字数 1770 浏览 1 评论 0原文

我不明白为什么

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-    
[__NSCFString allKeys]: unrecognized selector sent to instance 0x9367330'

每当我使用这段代码时

NSDictionary *nextArray = [_classDictionary 
valueForKeyPath:@"response.page_records.page_record"];
for (NSDictionary *roster2 in nextArray) {
NSArray *keys = [roster2 allKeys];
if ([keys containsObject:@"title"]){
    [pageName addObject:[roster2 objectForKey:@"title"]];
}
if ([keys containsObject:@"id"]) {
[pageID addObject:[roster2 objectForKey:@"id"]];
}
}

xcode都会继续抛出这个错误在尝试调试它之后我发现只有当该键只有一个对象时才会抛出异常。例如当“nextArray”是这样的时候:

 (
 {
    "class_id" = 0001;
    "id" = 1234;
    "title" = "First Page";
},
{
     "class_id" = 0002;
     "id" = 12345;
     "title" = Assignments;
 }
 )

代码运行时不会出现异常,但是当代码只是简单的时候

      {
         "class_id" = 0001;
         "id" = 1234;
         "title" = "First Page";
     }

就会抛出异常。为什么会发生这种情况呢?即使只有一个对象,键仍然包含对象标题。为什么抛出此异常还有其他想法吗?和括号有关系吗? (完全猜测)是否有更好的方法来调试到底发生了什么?

编辑:这是 _userDictionary。拥有 objectforKey: @"title" 的有序数组并避免上述错误的最佳方法是什么?

response =     {
    "status" = ok;
    "page_records" =         {
        "page" = 1;
        "page_count" = 1;
        "records_per_page" = 50;
        "total_record_count" = 2;
        "page_record" =             (
                            {
                "class_id" = 0001;
                "id" = 1234;
                "title" = "Test page";
            },
                            {
                "class_id" = 0002;
                "id" = 12345;
                "title" = "testing page 2";
            }
        );
    };
};
}

I can't figure out why xcode continues to throw this error

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-    
[__NSCFString allKeys]: unrecognized selector sent to instance 0x9367330'

whenever I use this code

NSDictionary *nextArray = [_classDictionary 
valueForKeyPath:@"response.page_records.page_record"];
for (NSDictionary *roster2 in nextArray) {
NSArray *keys = [roster2 allKeys];
if ([keys containsObject:@"title"]){
    [pageName addObject:[roster2 objectForKey:@"title"]];
}
if ([keys containsObject:@"id"]) {
[pageID addObject:[roster2 objectForKey:@"id"]];
}
}

After trying to debug it I found out that the exception is only thrown when there is only one object for the key. For example when "nextArray" is this:

 (
 {
    "class_id" = 0001;
    "id" = 1234;
    "title" = "First Page";
},
{
     "class_id" = 0002;
     "id" = 12345;
     "title" = Assignments;
 }
 )

the code runs without an exception, but when the code is simply

      {
         "class_id" = 0001;
         "id" = 1234;
         "title" = "First Page";
     }

The exception is thrown. Why would this be happening? The keys still contains the object title, even if there is only one object. Any other ideas why this exception is being thrown? Does it have something to do with the parenthesis? (total guess) Is there a better way to debug what is really going on?

EDIT: Here is the _userDictionary. What is the best way to have an ordered array of the objectforKey: @"title" and avoid the above error?

response =     {
    "status" = ok;
    "page_records" =         {
        "page" = 1;
        "page_count" = 1;
        "records_per_page" = 50;
        "total_record_count" = 2;
        "page_record" =             (
                            {
                "class_id" = 0001;
                "id" = 1234;
                "title" = "Test page";
            },
                            {
                "class_id" = 0002;
                "id" = 12345;
                "title" = "testing page 2";
            }
        );
    };
};
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你げ笑在眉眼 2025-01-01 12:22:39

在第一个示例中,您正在迭代字典数组,因此正在对数组调用 NSArray *keys = [roster2 allKeys]; 。但是,在第二个示例中,您只有一个字典。它不是一个字典数组。因此,您的循环 for (NSDictionary *roster2 in nextArray) 正在迭代字典的键,这些键只是字符串,而不是数组。因此,出现错误。

首先,你的命名很混乱。名为 nextArrayNSDictionary?试试这个:

id *response = [_classDictionary valueForKeyPath:@"response.page_records.page_record"];  
NSMutableArray *records;  

if ([response isKindOfClass: [NSDictionary class]]) {
    records = [[NSMutableArray alloc] init];
    [records addObject: response];
}
else {
    records = [NSMutableArray arrayWithArray: response];
}

for (NSDictionary *roster2 in records) {
    NSArray *keys = [roster2 allKeys];
    if ([keys containsObject:@"title"]){
        [pageName addObject:[roster2 objectForKey:@"title"]];
    }
    if ([keys containsObject:@"id"]) {
        [pageID addObject:[roster2 objectForKey:@"id"]];
    }
}

In your first example, you are iterating through an array of dictionaries, and hence, NSArray *keys = [roster2 allKeys]; is being called upon an array. However, in your second example, you have just one dictionary. It is not an array of dictionaries. So your loop for (NSDictionary *roster2 in nextArray) is iterating through the keys of your dictionary, which are just strings, and not arrays. Hence, the error.

First of all, your naming is confusing. An NSDictionary named nextArray? Try this:

id *response = [_classDictionary valueForKeyPath:@"response.page_records.page_record"];  
NSMutableArray *records;  

if ([response isKindOfClass: [NSDictionary class]]) {
    records = [[NSMutableArray alloc] init];
    [records addObject: response];
}
else {
    records = [NSMutableArray arrayWithArray: response];
}

for (NSDictionary *roster2 in records) {
    NSArray *keys = [roster2 allKeys];
    if ([keys containsObject:@"title"]){
        [pageName addObject:[roster2 objectForKey:@"title"]];
    }
    if ([keys containsObject:@"id"]) {
        [pageID addObject:[roster2 objectForKey:@"id"]];
    }
}
楠木可依 2025-01-01 12:22:39

错误消息包含您需要了解的所有内容:

[__NSCFString allKeys]: unrecognized selector

这意味着您正在尝试在 NSString 实例上调用方法 allKeys

让我们看看在哪里调用 allKeys

for (NSDictionary *roster2 in nextArray) {
    NSArray *keys = [roster2 allKeys];

roster2 是 NSString 的实例,而不是 NSDictionary。您期望 nextArray 包含 NSDictionary 对象,但它却包含 NSString 对象。

The error message contains everything you need to know:

[__NSCFString allKeys]: unrecognized selector

It means that you're trying to call the method allKeys on an instance of NSString.

Let's look at where you call allKeys:

for (NSDictionary *roster2 in nextArray) {
    NSArray *keys = [roster2 allKeys];

roster2 is an instance of NSString, not NSDictionary. You're expecting nextArray to contain NSDictionary objects, but it instead contains NSString objects.

成熟稳重的好男人 2025-01-01 12:22:39

不,这是因为 NSString 不响应 allKeys。控制台日志告诉您这一点——您需要更仔细地阅读它。

在 NeXT 样式的 plist 中,({}) 定义一个包含字典的数组。 {}定义一个字典。也就是说,这:

{
    "class_id" = 0001;
    "id" = 1234;
    "title" = "First Page";
}

在结构上与此相同:

(
    {
        "class_id" = 0001;
        "id" = 1234;
        "title" = "First Page";
    }
)

即使它们包含相同的信息。即使根数组中只有一个元素,您仍然需要告诉 plist 解析器那里有一个数组,因此您需要包含 ()你的逻辑来正确处理它。

编辑:鉴于您评论中的信息,解决方案不会那么简单。如果您的源数据是任意的,您需要检查数据的类型以查看它是否是 NSArrayNSDictionary,并进行适当的处​​理。例如:

id myData = [self plistFromArbitrarySource];
if (myData) {
    if ([myData isKindOfClass: [NSArray class]]) {
        for (NSDictionary *dict in myData) {
            [self parseDictionary:dict];
        }
    } else if ([myData isKindOfClass: [NSDictionary class]]) {
        [self parseDictionary:myData];
    }
}

No, it's because NSString doesn't respond to allKeys. The console log tells you this--you need to read it more carefully.

In NeXT-style plists, ({}) defines an array containing a dictionary. {} defines just a dictionary. That is, this:

{
    "class_id" = 0001;
    "id" = 1234;
    "title" = "First Page";
}

Is not structurally the same as this:

(
    {
        "class_id" = 0001;
        "id" = 1234;
        "title" = "First Page";
    }
)

Even though they contain the same information. Even if you have only one element in your root array, you still need to tell the plist parser that there is an array there, so you need to include ( and ) for your logic to handle it correctly.

Edit: Given the information in your comment, the solution will not be quite so simple. If your source data is arbitrary that way, you'll need to check the type of the data to see if it's an NSArray or NSDictionary, and handle it appropriately. For example:

id myData = [self plistFromArbitrarySource];
if (myData) {
    if ([myData isKindOfClass: [NSArray class]]) {
        for (NSDictionary *dict in myData) {
            [self parseDictionary:dict];
        }
    } else if ([myData isKindOfClass: [NSDictionary class]]) {
        [self parseDictionary:myData];
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文