Обновите UITableView, используя потоки - PullRequest
5 голосов
/ 31 июля 2010

Я создаю словарное приложение для iPhone, которое дает результат, пока пользователи печатают. Я использую потоки (NSThread) для обновления UITableView, чтобы основной поток не блокировался.

Однако происходит сбой, когда UITableView запрашивает источник данных о количестве строк (tableView: numberOfRowsInSection :) и я возвращаю, скажем, 10. Затем он запрашивает источник данных для ячеек 0-9 (tableView: cellForRowAtIndexPath: ). Но к тому времени, когда он запрашивает ячейку 7, источник данных уже изменился, и теперь у него всего 5 строк, что приводит к сбою.

Вот как я решаю проблему:

Я создаю NSLock в методе init.

А вот как выглядит источник данных:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [results count];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    [lock lock];
    if (indexPath.row < [results count]) {
        cell.textLabel.text = [results objectAtIndex:indexPath.row];
    }
    [lock unlock];

    return cell;
}

А вот код, который я использую для обновления таблицы:

[tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

Полностью решает проблему сбоя. Тем не менее, я думаю, что это может быть неэффективно, потому что источник данных должен блокировать / разблокировать каждый раз, когда он запрашивается для ячейки. И случай, о котором я упоминал выше, случается не так часто. У кого-нибудь есть лучшее представление о том, как эффективно решить эту проблему?

Большое спасибо!

Ответы [ 4 ]

4 голосов
/ 31 июля 2010

Не пытайтесь обновить пользовательский интерфейс из фонового потока. Это не сработает.

2 голосов
/ 31 июля 2010

Зачем вам использовать для этого отдельную тему?Сколько времени занимает поиск?0,1 секунды?Как это соотносится со временем, которое пользователь потратил, чтобы перестать печатать и посмотреть на экран?

Не усложняйте вещи!(Я возьму это обратно, если ваш поиск занимает более 0,7 секунд и не может быть оптимизирован; -)

1 голос
/ 16 апреля 2011

Просто здесь есть полезный ответ, вот мой ответ на другой похожий вопрос.

Не зная больше о вашем приложении, я думаю, что одним из лучших решений было бы сохранить массив нанить и отправлять обратно, когда другой поток должен внести изменения.Например:

dispatch_async(dispatch_get_main_queue(), ^{
                [array addObject:object];
                [tableView reloadData];
            });

Конечно, вы можете сделать намного более сложным с диспетчерским API, но он обрабатывает блокировку и все для вас.Определенно более элегантный, чем использование NSLock.Это работает только на iOS 4 или более поздней версии.

0 голосов
/ 18 марта 2013

Вы не можете обновить пользовательский интерфейс в фоновых потоках.

Использование Grand Central Displatch

Я объяснил здесь

https://stackoverflow.com/a/15469885/1239426

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...