NSMutableArray和valueforkey的问题

Alb*_*lby 1 iphone xcode uiwebview nsmutablearray uisearchdisplaycontroller

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

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>
Run Code Online (Sandbox Code Playgroud)

我没有问题地显示:

    NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"TestData" ofType:@"plist"]];  
        [self setContentsList:array];
Run Code Online (Sandbox Code Playgroud)

*问题是当我尝试搜索内容并且我想从搜索结果中获取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];
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

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];

}
Run Code Online (Sandbox Code Playgroud)

错误我得到:

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

小智 7

基础

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

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

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

    …
)
Run Code Online (Sandbox Code Playgroud)

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

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

(
    "Yahoo",
    "Google",
    …
)
Run Code Online (Sandbox Code Playgroud)

生成的数组不保存对原始数组的引用.

问题

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

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

这意味着这searchResults是一个包含标题列表的数组,这些标题不会自动与contentList数组中相应的字典相关.

您似乎想要保留原始字典,因为您已尝试创建字典:

// NSDictionary *dic= [[NSDictionary alloc]allKeysForObject:searchResults];
Run Code Online (Sandbox Code Playgroud)

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

NSString *arraySite = [[[self searchResults] objectAtIndex:indexPath.row]
    valueForKey:@"site"];
Run Code Online (Sandbox Code Playgroud)

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

一解决方案

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

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

现在每个元素searchResults都是一个包含site和的字典title.

-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];
}
Run Code Online (Sandbox Code Playgroud)