NSMutableArray 和 valueforkey 的问题

发布于 2024-11-03 21:17:40 字数 2644 浏览 0 评论 0原文

我使用 plist 文件来获取在表视图中显示的站点列表

plist 如下所示:

   <array>
        <dict>
            <key>site</key>
            <string>http://yahoo.com</string>
            <key>title</key>
            <string>Yahoo</string>
        </dict>
        <dict>
            <key>site</key>
            <string>http://google.com</string>
            <key>title</key>
            <string>Google</string>
        </dict>
//...etc
    </array>
    </plist>

我毫无问题地显示此内容:

    NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"TestData" ofType:@"plist"]];  
        [self setContentsList:array];

*问题是当我尝试在内容中搜索并且我想要从搜索结果中获取 valueforkey @"site" 以便在 didSelectRowAtIndexPath 中使用它: *

    NSMutableArray *contentsList;   
    NSMutableArray *searchResults;
    NSString *savedSearchTerm;
---------------------
- (void)handleSearchForTerm:(NSString *)searchTerm
{


    [self setSavedSearchTerm:searchTerm];

    if ([self searchResults] == nil)
    {
        NSMutableArray *array = [[NSMutableArray alloc] init];
        [self setSearchResults:array];
        [array release], array = nil;
    }

    [[self searchResults] removeAllObjects];

    if ([[self savedSearchTerm] length] != 0)
    {
        for (NSString *currentString in [[self contentsList] valueForKey:@"title"])
        {
            if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
            {
                [[self searchResults] addObject:currentString];
               // NSDictionary *dic= [[NSDictionary alloc]allKeysForObject:searchResults];
            }
        }
    }

}

didSelectRowAtIndexPath 用于在 webView 中打开站点

- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];


    NSString *arraySite = [[[self searchResults] objectAtIndex:indexPath.row] valueForKey:@"site"];

    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:arraySite]]];
    [self performSelector:@selector(showSearch:) withObject:nil afterDelay:0];

}

我得到错误:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSCFString 0x6042730> valueForUndefinedKey:]: this class is not key value coding-compliant for the key site.'

I use a plist file to get a list of site which are displayed in a tableview

The plist looks like this:

   <array>
        <dict>
            <key>site</key>
            <string>http://yahoo.com</string>
            <key>title</key>
            <string>Yahoo</string>
        </dict>
        <dict>
            <key>site</key>
            <string>http://google.com</string>
            <key>title</key>
            <string>Google</string>
        </dict>
//...etc
    </array>
    </plist>

I display this without problem:

    NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"TestData" ofType:@"plist"]];  
        [self setContentsList:array];

*The problem is when I try to search in the content and I want to get the valueforkey @"site" from the search result to use it in didSelectRowAtIndexPath: *

    NSMutableArray *contentsList;   
    NSMutableArray *searchResults;
    NSString *savedSearchTerm;
---------------------
- (void)handleSearchForTerm:(NSString *)searchTerm
{


    [self setSavedSearchTerm:searchTerm];

    if ([self searchResults] == nil)
    {
        NSMutableArray *array = [[NSMutableArray alloc] init];
        [self setSearchResults:array];
        [array release], array = nil;
    }

    [[self searchResults] removeAllObjects];

    if ([[self savedSearchTerm] length] != 0)
    {
        for (NSString *currentString in [[self contentsList] valueForKey:@"title"])
        {
            if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
            {
                [[self searchResults] addObject:currentString];
               // NSDictionary *dic= [[NSDictionary alloc]allKeysForObject:searchResults];
            }
        }
    }

}

The didSelectRowAtIndexPath is used to open the site in a webView

- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];


    NSString *arraySite = [[[self searchResults] objectAtIndex:indexPath.row] valueForKey:@"site"];

    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:arraySite]]];
    [self performSelector:@selector(showSearch:) withObject:nil afterDelay:0];

}

ERROR I GET :

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSCFString 0x6042730> valueForUndefinedKey:]: this class is not key value coding-compliant for the key site.'

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

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

发布评论

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

评论(1

高速公鹿 2024-11-10 21:17:40

基础知识

当您从该 plist 读取数组时,该数组如下所示:

(
    {
        "site"  = "http://yahoo.com",
        "title" = "Yahoo"
    },

    {
        "site"  = "http://google.com",
        "title" = "Google"
    },

    …
)

它是一个其元素是字典的数组,每个字典包含两个键及其对应的值。

当您在传递键 title 的数组上使用 KVC 方法 -valueForKey: 时,它会返回另一个数组,其元素是与该键对应的值:

(
    "Yahoo",
    "Google",
    …
)

生成的数组不会t 保存对原始数组的引用。

问题

-handleSearchForTerm: 中,您得到一个仅包含原始数组中标题的数组。对于每个标题,您有选择地将其添加到 searchResults 数组中:

for (NSString *currentString in [[self contentsList] valueForKey:@"title"])
{
    …
    [[self searchResults] addObject:currentString];
}

这意味着 searchResults 是一个包含标题列表的数组,这些标题不会自动与contentList 数组。

看来您想保留原始字典,因为您尝试创建字典:

// NSDictionary *dic= [[NSDictionary alloc]allKeysForObject:searchResults];

并且在另一种方法中,您尝试获取与 site 键对应的值:

NSString *arraySite = [[[self searchResults] objectAtIndex:indexPath.row]
    valueForKey:@"site"];

如上所述,您的 searchResults 包含表示标题的字符串列表。当你从这个数组中获取一个元素时,它只是一个字符串 - 因此 -valueForKey:@"site" 没有意义,Cocoa 会警告你字符串不符合键值对关键站点

一种解决方案

据我所知,您应该将从 plist 文件中读取的原始字典存储在 searchResults 数组中。在 -handleSearchForTerm: 中,执行以下操作:

for (NSDictionary *currentSite in [self contentsList])
{
    NSString *title = [currentSite objectForKey:@"title"];
    if ([title rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
    {
        [[self searchResults] addObject:currentSite];
    }
}

现在 searchResults 中的每个元素都是包含 sitetitle 的字典。

-tableView:didSelectRowAtIndexPath:中,使用字典获取对应的site

- (void)tableView:(UITableView *)tableView
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    NSDictionary *selectedSite = [[self searchResults] objectAtIndex:indexPath.row];
    NSString *siteStringURL = [selectedSite objectForKey:@"site"];
    // or, if you prefer everything in a single line:
    // NSString *siteStringURL = [[[self searchResults] objectAtIndex:indexPath.row] objectForKey:@"site"];

    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:siteStringURL]]];
    [self performSelector:@selector(showSearch:) withObject:nil afterDelay:0];
}

The Basics

When you read the array from that plist, the array looks like the following:

(
    {
        "site"  = "http://yahoo.com",
        "title" = "Yahoo"
    },

    {
        "site"  = "http://google.com",
        "title" = "Google"
    },

    …
)

It is an array whose elements are dictionaries, each dictionary containing two keys and their corresponding values.

When you use the KVC method -valueForKey: on the array passing the key title, it returns another array whose elements are the values corresponding to that key:

(
    "Yahoo",
    "Google",
    …
)

The resulting array doesn’t hold a reference to the original array.

The Problem

In -handleSearchForTerm:, you get an array containing only the titles from the original array. For each title, you selectively add it to the searchResults array:

for (NSString *currentString in [[self contentsList] valueForKey:@"title"])
{
    …
    [[self searchResults] addObject:currentString];
}

This means that searchResults is an array containing a list of titles which are not automatically related to the corresponding dictionaries in the contentList array.

It seems like you want to keep the original dictionary because you’ve tried to create a dictionary:

// NSDictionary *dic= [[NSDictionary alloc]allKeysForObject:searchResults];

and, in another method, you’re trying to obtain the value corresponding to the site key:

NSString *arraySite = [[[self searchResults] objectAtIndex:indexPath.row]
    valueForKey:@"site"];

As mentioned, your searchResults contains a list of strings representing titles. When you obtain an element from this array, it’s only a string — hence -valueForKey:@"site" doesn’t make sense, and Cocoa warns you that a string is not key-value compliant for the key site.

One Solution

From what I can tell, you should be storing, in your searchResults array, the original dictionary read from the plist file. In -handleSearchForTerm:, do the following:

for (NSDictionary *currentSite in [self contentsList])
{
    NSString *title = [currentSite objectForKey:@"title"];
    if ([title rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
    {
        [[self searchResults] addObject:currentSite];
    }
}

Now every element in searchResults is a dictionary containing both site and title.

In -tableView:didSelectRowAtIndexPath:, use the dictionary to obtain the corresponding site:

- (void)tableView:(UITableView *)tableView
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    NSDictionary *selectedSite = [[self searchResults] objectAtIndex:indexPath.row];
    NSString *siteStringURL = [selectedSite objectForKey:@"site"];
    // or, if you prefer everything in a single line:
    // NSString *siteStringURL = [[[self searchResults] objectAtIndex:indexPath.row] objectForKey:@"site"];

    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:siteStringURL]]];
    [self performSelector:@selector(showSearch:) withObject:nil afterDelay:0];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文