1

ユーザーが入力したテキストに従ってUITableViewをフィルタリングする検索フィールドを実装しています。
TableViewは、NSString(表示および検索するデータ)を保持する配列から構築され、 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

これを試して:

最初の3つの位置について、26個のインデックスセットを作成します。各セットは、その文字(小文字)を含むアイテムの配列インデックスを表します。つまり、idx=100のエントリが「formula」で始まるとします。最初の位置の「f」を表すインデックスセットには、インデックス「100」が含まれます。2番目の文字「o」のインデックスセットにはインデックス100が含まれ、3番目の文字「r」のインデックスセットには10​​0が含まれます。

ユーザーが文字「f」を入力すると、「f」で始まるすべての配列項目のインデックスセットがすぐに得られます(主要な配列のサブセットをすばやく作成できます)。次に「o」を入力すると、最初の一致と2番目の一致のインデックスの共通部分を見つけることができます。3番目の同上。次に、最初の3つのインデックスが一致するメジャー配列のサブ配列を作成します。これにはインデックスセットを使用できます。

この大幅に削減されたアレイを使用すると、元々行っていたようにブルートフォースマッチングを実行できるようになります。

于 2012-09-01T23:03:05.250 に答える