У меня есть структура данных (в plist), которая выглядит примерно так:
Здесь у меня есть 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;
}