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 设置列标题文本