UISearchDisplayController 与 UISearchBar 和 UITableView - 如何避免“实时结果”?

发布于 2024-10-10 12:53:02 字数 2544 浏览 4 评论 0原文

我已经使用 UISearchDisplayController 和 UITableView 实现了 SearchBar 来显示搜索结果。我使用 libxml2 和 xpath 来解析 HTML 网站并搜索源代码中所需的内容。由于我是 ObjC 的新手,所以我首先使用 Apple 提供的示例项目 TableSearch 来进行搜索和显示部分。一切都很好,我可以解析网站中的特定内容,并在它们出现在网站上时正确组合它们,并将它们显示在不同的 TableView 行视图中。我想使用用户输入来搜索特定网站。我只有以下问题:

如果您查看该项目 TableSearch< /a> (类 MainViewController.m),您会注意到它更新了“filteredListContent”并在用户键入时重新加载自动显示它的 TableView:

[...]

#pragma mark -
#pragma mark Content Filtering

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
 /*
  Update the filtered array based on the search text and scope.
  */

 [self.filteredListContent removeAllObjects]; // First clear the filtered array.

 /*
  Search the main list for products whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array.
  */
 for (Product *product in listContent)
 {
  if ([scope isEqualToString:@"All"] || [product.type isEqualToString:scope])
  {
   NSComparisonResult result = [product.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame)
   {
    [self.filteredListContent addObject:product];
            }
  }
 }
}


#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString scope:
   [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];

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


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
   [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];

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


@end

您可以想象,当我使用我的实现进行解析和搜索时,它需要一些内存当用户打字时重复调用它以显示“实时结果”时,这一点尤其重要。当我只使用块的第一行进行解析和搜索(使用 URL 初始化 NSData 对象)时,SearchBar 开始滞后,并在每个字符键入后延迟几秒钟。当我使用整个块时,应用程序崩溃。我的问题如下:

如何在执行搜索之前等待键盘上的“搜索”或“返回”按钮被点击,或者在哪里以及如何检查按钮是否被点击?很抱歉这个可能微不足道的问题。

I have implemented a SearchBar using a UISearchDisplayController and a UITableView to display the search results in. I am using libxml2 and xpath to parse an HTML website and search the content needed in the source code. Since I am new to ObjC, I have used the sample project TableSearch provided by Apple for the searching and displaying part as a start. Everything works fine with this, I can parse specific contents from a website, and combine them correctly as they appear on the website and have them displayed in the different TableView rows' views. I want to use the user input to search a specific website for it. I only have the following problem:

If you take a look at the project TableSearch (class MainViewController.m), you will notice that it updates the "filteredListContent" and reloads the TableView displaying it automatically as the user types:

[...]

#pragma mark -
#pragma mark Content Filtering

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
 /*
  Update the filtered array based on the search text and scope.
  */

 [self.filteredListContent removeAllObjects]; // First clear the filtered array.

 /*
  Search the main list for products whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array.
  */
 for (Product *product in listContent)
 {
  if ([scope isEqualToString:@"All"] || [product.type isEqualToString:scope])
  {
   NSComparisonResult result = [product.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame)
   {
    [self.filteredListContent addObject:product];
            }
  }
 }
}


#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString scope:
   [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];

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


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
   [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];

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


@end

You can imagine that it requires some memory when I use my implementation for parsing and searching and it is especially critical when it is called repeatedly while the user is typing in order to display "live results". When I only use the first line of my block for parsing and searching (initializing an NSData object with a URL) the SearchBar starts lagging and is delayed for a few seconds after each character typed. When I use the whole block, the app crashes. My question is the following:

How is it possible to wait for the "Search" or "Return" button on the keyboard to be tapped before a search is performed or where and how can I check whether the button was tapped? Sorry for this possibly trivial question.

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

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

发布评论

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

评论(1

始于初秋 2024-10-17 12:53:02

让您的委托对象也是搜索栏的委托,并按如下方式实现这些方法:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text]
                               scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    return NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    return NO;
}

这将防止表视图在用户键入或更改范围时重新加载,并在单击搜索按钮时重新加载。但是,当输入第一个字符时,该表会重新加载。我还没有找到阻止这种行为的方法。事实上,当输入第一个字符时,表可能会显示没有结果。

Make your delegate object also the delegate of the search bar, and implement these methods as follows:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text]
                               scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    return NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    return NO;
}

This will prevent the table view from reloading as the user types or changes scope, and reloads when the search button is clicked. However, the table does reload when the first character is entered. I have not yet found a way to prevent this action. As it is, the table will probably say no results when the first character is entered.

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