搜索 NSDictionary 的 NSArray(其中包含 NSDictionary 的 NSArray,重复)

发布于 2024-11-16 17:23:18 字数 3732 浏览 1 评论 0原文

我有一个数据结构(在 plist 中),看起来像这样:

在此处输入图像描述

我这里有一个NSDictionaryNSArray。每个 NSDictionary 有两个键:

Title
Link (recursive)

这形成了一个树状结构,具有可变长度的分支,即一些分支可以在第 0 级消亡,而有些分支可以达到第 3 级或更高级别。

我在 UITableView 中展示了这个结构(在 UINavigationController 的帮助下)。这很容易。

注意:点击叶节点时 (由 NSDictionary 对象表示 以Nil作为“链接”), 事件被触发,即模型窗口 出现一些信息。

现在,我需要添加搜索支持。

搜索栏将出现在 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;
}

I have a data-structure (in plist) that looks something like this:

enter image description here

What i have here is an NSArray of NSDictionary. Each NSDictionary has two keys:

Title
Link (recursive)

This forms a tree like structure, with variable length branches i.e. some branches can die at level 0, and some can be as large as level 3 or more.

I'm showing this structure in UITableView (with a little help from UINavigationController). This was easy enough.

Note: On tapping the Leaf Node
(represented by NSDictionary object
with Nil or Zero as "Link"), an
event is triggered i.e. Model window
appears with some information.

Now, i need to add Search support.

Search bar will appear above UITabeView (for Level 0). I need to come-up with a way to search this tree like structure, and then show the results using UISearchDisplayController, and then allow users to navigate the results as well.

How?... is where i'm a little stuck
and need some advise.

The search has to be quick, because we want search as you type.

p.s. I've thought of translating this data structure to CoreData, and it's still lurking in my mind. If you think it can help in this case, please advise.


Edit:
Here's my current solution, which is working (by the way):

#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;
}

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

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

发布评论

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

评论(1

予囚 2024-11-23 17:23:18

核心数据能够非常有效地在数据存储中执行搜索,并且可以有效地将搜索扩展到更多级别。另外,如果您使用 NSFetchedResultsController对于 TableView 来说,它几乎肯定会提高内存效率 - 最坏的情况是在任何给定时间只加载一级数组。最好的情况要好得多,因为它只有 将一些对象放入数组中。华泰

Core Data would be able to perform the search in the data store pretty efficiently, and would scale the search to more levels efficiently. Also, if you use NSFetchedResultsController for the TableView it would almost certainly be more memory efficient - the worst case would only have one level array loaded at any given time. And the best case is considerably better, as it would only have faulted a few objects into the array. HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文