Проблема с NSMutableArray и valueforkey - PullRequest
1 голос
/ 28 апреля 2011

Я использую файл 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];

* Проблема заключается в том, что когда я пытаюсь выполнить поиск по содержимому и хочу получить значениеforkey @ "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 используется для открытия сайта в веб-представлении

- (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.'

1 Ответ

7 голосов
/ 28 апреля 2011

Основы

Когда вы читаете массив из этого списка, он выглядит следующим образом:

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

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

    …
)

Это массив, элементы которого являются словарями, каждый словарь содержит два ключа и соответствующие им значения.

Когда вы используете метод KVC -valueForKey: для массива, передающего ключ title, он возвращает другой массив, элементами которого являются значения, соответствующие этому ключу:

(
    "Yahoo",
    "Google",
    …
)

Полученный массив не содержит ссылку на исходный массив.

Проблема

В -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" не имеет смысла, и Какао предупреждает вас, что строка не соответствует значению ключа для ключа 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];
    }
}

Теперь каждый элемент в 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];
}
...