UISearchBar と UITablevView を備えた ViewController があります。テーブルビューは配列内のアイテムのリストを表示するだけですが、フィルタリングされたアイテムのリストを で表示したいと思いますfilteredArrayUsingPredicate
。述語NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ OR SELF LIKE[cd] %@", searchText,searchText];
を使用してフィルター処理された配列を取得できます。フィルター処理された配列のカウントを出力すると、アイテムの数は正しくなります。しかし、テーブルに表示しようとすると、次のエラーでクラッシュが発生します。
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndexedSubscript:]: index 3 beyond bounds [0 .. 2]'
検索バーとテーブルへの入力のコードは次のとおりです。
@interface ViewController (){
NSMutableArray<NSString*> *_items;
NSMutableArray<NSString*> *_filtered;
bool _searching;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self->_items = @[@"iphone",@"ipad",@"ipod",@"imac"];
self->_filtered = [[NSMutableArray alloc] initWithArray:self->_items];
self->_table.dataSource = self;
[self->_table setDelegate:self];
[self->_search setDelegate:self];
self->_searching = false;
}
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText{
self->_searching = true;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ OR SELF LIKE[cd] %@", searchText,searchText];
self->_filtered = [self->_items filteredArrayUsingPredicate:predicate];
NSLog(@"%lu",(unsigned long)[self->_filtered count]);
[self->_table reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self->_items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
if(self->_searching)
cell.textLabel.text = self->_filtered[indexPath.row];
else
cell.textLabel.text = self->_items[indexPath.row];
return cell;
}
@end
クラッシュの原因となっていると思われる行は、この
メソッドで検索を true に設定し、[self->_table reloadData];
検索が true であるかどうかを確認し、それ以外の場合は項目を表示します。しかし、データをリロードして、フィルタリングされた結果を表示するように指示すると、クラッシュが発生する理由がわかりません。- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText
cellForRowAtIndexPath