iOS 8 で導入された UISearchController API を使用して検索を実装しています。検索結果コントローラーと検索結果アップデーターの両方として機能する UITableViewController サブクラスがあります。このコントローラーは、検索結果を表形式で表示する役割を果たします。
searchBar のテキストが変更されるたびに、検索 API は-updateSearchResultsForSearchController:
テーブル ビュー コントローラーで UISearchControllerUpdating メソッドを呼び出します。このメソッドでは、新しい検索文字列に基づいて検索結果を更新してから、 を呼び出します[self.tableview reloadData]
。
また、結果のリストで検索文字列の出現箇所を強調表示しようとしています。テーブル ビュー セルの attributedText を、ハイライトを含む属性付き文字列に設定することで、これを実現します。
次の動作が見られます。
- 最初のキーストロークの後、ハイライトが正しく表示される
- 2 回目のキーストロークの後、すべてのハイライトが消えます。
- セルの文字列の先頭に強調表示された領域がある場合、文字列の残りの部分であっても、すべての強調表示が表示されます
いくつかの試行錯誤の後、これはテーブルビューやセルとは何の関係もないように見え、すべてUILabelと関係があることがわかりました。attributedText プロパティが 2 回目に設定されると、ラベルは常にハイライトを失うようです。本当に一度だけ設定できますか?
私のコードの一部
テーブル ビュー データ ソース:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* plainCell = @"plainCell";
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:plainCell];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:plainCell];
}
JFDHelpEntry* entry = searchResults[indexPath.row];
cell.textLabel.attributedText = [self highlightedString:entry.title withSearchString:currentSearchString];
return cell;
}
テキストのハイライトを生成するメソッド:
- (NSAttributedString*)highlightedString:(NSString*)string withSearchString:(NSString*)searchString
{
NSMutableAttributedString* result = [[NSMutableAttributedString alloc] initWithString:string];
NSArray* matchedRanges = [self rangesOfString:searchString inString:string];
for (NSValue* rangeInABox in matchedRanges) {
[result addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:[rangeInABox rangeValue]];
}
return result;
}
強調表示する範囲を見つけるメソッド:
- (NSArray*)rangesOfString:(NSString*)needle inString:(NSString*)haystack
{
NSMutableArray* result = [NSMutableArray array];
NSRange searchRange = NSMakeRange(0, haystack.length);
NSRange foundRange;
while (foundRange.location != NSNotFound) {
foundRange = [haystack rangeOfString:needle options:NSCaseInsensitiveSearch range:searchRange];
if (foundRange.location != NSNotFound) {
[result addObject:[NSValue valueWithRange:foundRange]];
searchRange.location = foundRange.location + foundRange.length;
}
searchRange.length = haystack.length - searchRange.location;
}
return result;
}
何か案は?ありがとう!