1

我正在实现一个根据用户输入的文本过滤 UITableView 的搜索字段。
TableView 是由一个包含 NSStrings(要显示和搜索的数据)的数组构建的,并且可能包含6000 多个项目
当用户开始搜索时,我正在实现该-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText方法。

我的代码可以工作,但是,当数据数组很大时,它会非常慢并且会造成非常糟糕的用户体验(我的 iPhone 4s 卡住了好几秒钟)。

我实现搜索的方式(在上面提到的方法中)是这样的:

NSMutableArray *discardedItems = [[NSMutableArray alloc] init]; // Items to be removed
searchResultsArray = [[NSMutableArray alloc] initWithArray:containerArray]; // The array that holds all the data

// Search for matching results
for (int i=0; i<[searchResultsArray count]; i++) {   
    NSString *data = [[containerArray objectAtIndex:i] lowercaseString];
    NSRange r = [data rangeOfString:searchText];
    if (r.location == NSNotFound) {
        // Mark the items to be removed
        [discardedItems addObject:[searchResultsArray objectAtIndex:i]];
    }
}
// update the display array
[searchResultsArray removeObjectsInArray:discardedItems];
[myTableView reloadData];

我不认为循环一个包含几千个项目的数组会导致任何问题......
任何建议都将不胜感激!

更新 我刚刚意识到大部分时间是这样的:

[searchResultsArray removeObjectsInArray:discardedItems];
4

2 回答 2

1

尝试快速枚举方式,我的片段:

- (void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
    if(text.length == 0)
    {
        self.isFiltered = NO;
    }
    else
    {
        self.isFiltered = YES;
        self.searchArray = [NSMutableArray arrayWithCapacity:self.places.count];

        for (PTGPlace* place in self.places)
        {
            NSRange nameRange = [place.name rangeOfString:text options:NSCaseInsensitiveSearch];

            if(nameRange.location != NSNotFound)
            {
                [self.searchArray addObject:place];
            }
        }
    }

    [self.tableView reloadData];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if(self.isFiltered)
        return self.searchArray.count;
    else
        return self.places.count;
}

在 cellForRowAtIndexPath 中:

    PTGPlace *place = nil;

    if(self.isFiltered)
        place = [self.searchArray objectAtIndex:indexPath.row];
    else
        place = [self.places objectAtIndex:indexPath.row];

    // Configure the cell...
    cell.textLabel.text = place.name;
    cell.detailTextLabel.text = [place subtitle];
于 2012-09-01T20:16:22.073 回答
0

尝试这个:

对于前三个位置,创建 26 个索引集,每个表示具有该字母的项目的数组索引(只是小写)。也就是说,假设 idx=100 处的条目以“公式”开头。在第一个位置表示“f”的索引集将包含索引“100”。为第二个字符“o”设置的索引将包含索引 100,为第三个字符“r”设置的索引将包含 100。

当用户键入字符“f”时,您会立即获得所有以“f”开头的数组项的索引集(并且可以快速创建主要数组的子集)。当接下来键入“o”时,您可以找到第一个匹配项与第二个匹配项中的索引的交集。第三个同上。现在制作一个前三个索引匹配的主数组的子数组 - 您可以为此使用索引集。

使用这个大大减少的数组,您现在可以像原来一样进行蛮力匹配。

于 2012-09-01T23:03:05.250 回答