Поиск NSArray NSDictionary (который содержит NSArray NSDictionary, неоднократно) - PullRequest
1 голос
/ 22 июня 2011

У меня есть структура данных (в plist), которая выглядит примерно так:

enter image description here

Здесь у меня есть NSArray из NSDictionary.Каждый NSDictionary имеет два ключа:

Title
Link (recursive)

Это формирует древовидную структуру с ветвями переменной длины, то есть некоторые ветви могут умереть на уровне 0, а некоторые могут достигать уровня 3 или более.

Я показываю эту структуру в UITableView (с небольшой помощью от UINavigationController).Это было достаточно просто.

Примечание. При нажатии на конечный узел (представлен объектом NSDictionary с Nil или Ноль в качестве «Link»)событие вызвано, т.е. окно модели появляется с некоторой информацией.

Теперь мне нужно добавить поддержку поиска.

Панель поиска появится над UITabeView (для уровня 0).Мне нужно придумать способ поиска по этому древовидному типу структуры, а затем показать результаты с помощью UISearchDisplayController, а затем позволить пользователям также перемещаться по результатам.

Как? ..... я немного застрял и мне нужен совет.

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

ps Я думал о переводе этой структуры данных в CoreData, и она все еще скрывается в моей памяти.Если вы думаете, что это может помочь в этом случае, пожалуйста, сообщите.


Редактировать: Вот мое текущее решение, которое работает (кстати):

#pragma mark -
#pragma mark UISearchDisplayController methods 

- (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar {
    NSLog(@"%s", __FUNCTION__);
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    NSLog(@"%s", __FUNCTION__);
    [self filterCategoriesForSearchText:searchString
                               scope:[controller.searchBar selectedScopeButtonIndex]];

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    NSLog(@"%s", __FUNCTION__);
    [self filterCategoriesForSearchText:[controller.searchBar text]
                               scope:[controller.searchBar selectedScopeButtonIndex]];

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

#pragma mark UISearchDisplayController helper methods

- (void)filterCategoriesForSearchText:(NSString *)searchText scope:(NSInteger)scope {
    self.filteredCategories = [self filterCategoriesInArray:_categories forSearchText:searchText];

    NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:KEY_DICTIONARY_TITLE ascending:YES] autorelease];
    [self.filteredCategories sortUsingDescriptors:[NSArray arrayWithObjects:descriptor, nil]];
}

- (NSMutableArray *)filterCategoriesInArray:(NSArray *)array forSearchText:(NSString *)searchText {
    NSMutableArray *resultArray = [NSMutableArray array];
    NSArray *filteredResults = nil;

    // Apply filter to array
    // For some weird reason this is not working. Any guesses? [NSPredicate predicateWithFormat:@"%@ CONTAINS[cd] %@", KEY_DICTIONARY_TITLE, searchText];
    NSPredicate *filter = [NSPredicate predicateWithFormat:@"Title CONTAINS[cd] %@", searchText];
    filteredResults = [array filteredArrayUsingPredicate:filter];

    // Store the filtered results (1)
    if ((filteredResults != nil) && ([filteredResults count] > 0)) {
        [resultArray addObjectsFromArray:filteredResults];
    }

    // Loop on related records to find the matching results
    for (NSDictionary *dictionayObject in array) {
        NSArray *innerCategories = [dictionayObject objectForKey:KEY_DICTIONARY_LINK];

        if ((innerCategories != nil) && ([innerCategories count] > 0)) {
            filteredResults = [self filterCategoriesInArray:innerCategories forSearchText:searchText];

            // Store the filtered results (2)
            if ((filteredResults != nil) && ([filteredResults count] > 0)) {
                [resultArray addObjectsFromArray:filteredResults];
            }
        }
    }

    return resultArray;
}

1 Ответ

1 голос
/ 26 июня 2011

Базовые данные сможет довольно эффективно выполнять поиск в хранилище данных и эффективно масштабировать поиск до большего уровня.Кроме того, если вы используете NSFetchedResultsController для TableView, это почти наверняка будет более эффективным с точки зрения памяти - в худшем случае будет загружен только один массив уровней в любой момент времени.И лучший случай значительно лучше, так как в массиве будет неисправно нескольких объектов.НТН

...