UITableView обновляет результаты из UISearchBar

У меня есть ViewController с UISearchBar и UITablevView. Tableview просто отображает список элементов в массиве, но я хотел бы, чтобы он отображал отфильтрованный список элементов с 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

Строка, которая, кажется, вызывает сбой, - это [self->_table reloadData]; в - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText. В этом методе я установил для поиска значение true, а в моем cellForRowAtIndexPath я проверяю, верен ли поиск, затем отображаю отфильтрованные результаты, в противном случае отображаю элементы. Но я не понимаю, почему происходит сбой, если я перезагружаю данные и говорю им отображать отфильтрованные результаты.


person Nina    schedule 18.11.2019    source источник


Ответы (1)


Вы возвращаете количество нефильтрованных элементов из numberOfRowsInSection, когда вы должны возвращать количество отфильтрованных элементов, если _searching истинно.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (_searching) {
        return _filtered.count;
    }

    return _items.count;
}
person Tyler    schedule 18.11.2019
comment
Знаете ли вы хороший способ отображения нефильтрованных результатов после отмены поиска? Потому что я не хочу везде вызывать [table reload].. - person Nina; 18.11.2019
comment
Нет, вам в значительной степени нужно вызывать reloadData для повторного заполнения табличного представления всякий раз, когда данные, которые вы хотите отобразить, радикально меняются. - person Tyler; 18.11.2019