iPhone - UITableView 的问题 - 重新加载数据并且没有命中

Posted

技术标签:

【中文标题】iPhone - UITableView 的问题 - 重新加载数据并且没有命中【英文标题】:iPhone - Problems with UITableView - reload data & no hits 【发布时间】:2010-01-06 20:09:06 【问题描述】:

我正在使用这个 Apple 的示例代码示例:

http://developer.apple.com/iPhone/library/samplecode/TableSearch/index.html

在本例中,UITableView 在启动时获取内容列表。点击 UISearchBar 并输入,内容列表将被过滤,同时检查 ScopeBar 的范围。

我必须将这种“即时搜索”重建为“正常搜索”:一开始我没有 TableView 的数据。用户应该点击搜索栏,输入一些内容,按下“搜索”按钮,搜索请求将被发送到网络服务器。网络服务器的响应将被放入 TableView 中,用户可以切换范围以过滤结果集。更改 SearchBar 的值不会过滤结果列表。只有按下“搜索”才能发起搜索请求。

我获取了示例代码并重新构建了它(源代码在底部)。 但我有两个问题。

    在 SearchViewController 的初始调用(使用 TabBar、SearchBar、ScopeBar、TableView)时,一切正常。有一个空的 TableView。但是,在 SearchBar 中单击并键入任何一个字符,都会出现一条消息,指出“没有命中”。我怎么能避免呢?仅当用户按“搜索”并且确实没有匹配项时,才会出现此消息。 我的第二个问题:键入“hello”并按“Search”,TableView 没有列出结果。如果我单击“中止”或在不同的范围内,将列出结果。所以一定有诸如丢失的“重新加载”之类的东西?!

我希望有人可以帮助我。 非常感谢您的到来和最诚挚的问候。

我的源代码:

@implementation SearchViewController

@synthesize listContent, filteredListContent, savedSearchTerm, savedScopeButtonIndex, searchWasActive;

- (void)viewDidLoad 
    // restore search settings if they were saved in didReceiveMemoryWarning.
    if (self.savedSearchTerm) 
        [self.searchDisplayController setActive:self.searchWasActive];
        [self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
        [self.searchDisplayController.searchBar setText:savedSearchTerm];
        self.savedSearchTerm = nil;
    


- (void)viewDidUnload 
    // Save the state of the search UI so that it can be restored if the view is re-created.
    self.searchWasActive = [self.searchDisplayController isActive];
    self.savedSearchTerm = [self.searchDisplayController.searchBar text];
    self.savedScopeButtonIndex = [self.searchDisplayController.searchBar selectedScopeButtonIndex];
    self.filteredListContent = nil;


- (void)dealloc 
    [listContent release];
    [filteredListContent release];
    [super dealloc];


- (void)setData 
    self.listContent = [NSMutableArray arrayWithCapacity:3];
    [self.listContent addObject:[SearchObjects itemWithType:@"AAA" name:@"Test1"]];
    [self.listContent addObject:[SearchObjects itemWithType:@"BBB" name:@"Test2"]];
    [self.listContent addObject:[SearchObjects itemWithType:@"BBB" name:@"Test3"]];

    // create a filtered list
    self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
    [self.tableView reloadData];
    self.tableView.scrollEnabled = YES;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    //If the requesting table view is the search display controller's table view, return the count of the filtered list, otherwise return the count of the main list.
    if (tableView == self.searchDisplayController.searchResultsTableView) 
        return [self.filteredListContent count];
     else 
        return [self.listContent count];
    


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *kCellID = @"cellID";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
    if (cell == nil) 
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    

    /* If the requesting table view is the search display controller's table view, configure the cell using the filtered content, otherwise use the main list. */
    SearchObjects *searchObject = nil;
    if (tableView == self.searchDisplayController.searchResultsTableView) 
        searchObject = [self.filteredListContent objectAtIndex:indexPath.row];
     else 
        searchObject = [self.listContent objectAtIndex:indexPath.row];
    
    cell.textLabel.text = searchObject.name;
    return cell;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    // HERE IS THE SOURCE CODE FOR PUSHING TO THE NEXT VIEW


- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar 
    // DO SOME CALCULATIONS… AND THE setData METHOD IS CALLED


- (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 whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array. */
    for (SearchObjects *searchObject in listContent) 
        if ([scope isEqualToString:@"All"] || [searchObject.type isEqualToString:scope]) 
        NSComparisonResult result = [searchObject.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame) 
                [self.filteredListContent addObject:searchObject];
            
        
    


- (void)filterContentForScope:(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 whose type matches the scope (if selected); add items that match to the filtered array. */
    for (SearchObjects *searchObject in listContent) 
        if ([scope isEqualToString:@"All"] || [searchObject.type isEqualToString:scope]) 
            [self.filteredListContent addObject:searchObject];
        
    


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
    [self filterContentForScope:[[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 filterContentForScope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
    // Return YES to cause the search result table view to be reloaded.
    return YES;

@end

【问题讨论】:

【参考方案1】:

对于您的第一个问题,您应该为搜索栏设置一个委托,然后实现– searchBarSearchButtonClicked: 并将您的搜索代码放在那里。您可能还需要实现其他方法,例如 – searchBarTextDidEndEditing:– searchBar:textDidChange:,并确保它们不执行搜索。

对于您的第二个问题,您可能希望再次使用 – searchBarSearchButtonClicked: 中的委托重新加载 tableView,以确保它在您已经搜索后发生。您可以使用[tableView reloadData] 来完成此操作。

【讨论】:

嗯,我不明白。我已经有一个方法“searchBarSearchButtonClicked:”。在此我向服务器发送请求,“setData”方法将数据设置到 TableView 并执行 reloadData,但这不起作用。 您是否覆盖了 searchBarTextDidChange 以防止可能重新加载数据? 我解决了这个问题。我设置了一个标志,只有当标志为真时,这表明搜索已完成,然后我才返回 YES;在委托方法中 searchDisplayController:controller shouldReloadTableFor... 另一个问题出在 listContent 中。它执行 reloadData,但重点是过滤的内容列表! 嗨蒂姆,我正在做类似的事情并且有同样的问题,但我无法解决它。我尝试按照您在此处描述的方式设置一个标志,并且如果已收到来自服务器的响应,则仅在这两个委托方法中返回 YES。但是,我没有看到在对服务器的查询之后调用的那些方法。你如何让表格重新加载过滤结果?这是由服务器的响应触发的吗?另外,我在上面的代码中没有看到您在此处描述的第二个问题(使用 reloadData)。【参考方案2】:

问题已解决,见 cmets。

【讨论】:

以上是关于iPhone - UITableView 的问题 - 重新加载数据并且没有命中的主要内容,如果未能解决你的问题,请参考以下文章

iPhone:UITableView 部分

iPhone + UITableView

iPhone 5 UITableView 不显示

在 iPhone 中为 UITableView 设置列标题文本

将 UITableView 大小调整为 iPhone 5/5s

Iphone:UITableView 标题行在 6 行后重复