Подтвердить что ты не робот

UITableViewCell textLabel не обновляется до тех пор, пока не будет прокрутка или не произойдет при использовании GCD

Может кто-нибудь помочь мне понять это, пожалуйста?

My UITableViewCell textLabel, не обновляется до тех пор, пока я не прокрутит или не коснусь.

Загружается ViewController, он показывает правильное количество ячеек. Но контент пуст. Мне нужно прикоснуться к ней или прокрутить, чтобы появился текст textLabel.

Я делаю что-то не так здесь?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    [[cell textLabel] setFont: [UIFont systemFontOfSize: 32.0]];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSDictionary * data = [self timeForObject: [self.months objectAtIndex:indexPath.row]];

        dispatch_async(dispatch_get_main_queue(), ^{

            NSString *time      = [data objectForKey:@"Time"];
            NSString *totalTime = [data objectForKey:@"Total Time"];

            NSString * textLabel  = [NSString stringWithFormat:@" %@ %@",
                                        time, totalTime];

            [[cell textLabel] setText:textLabel];



        });
    });

    return cell;
}

Любая помощь приветствуется

Спасибо!

Нуну

EDIT:

Вызов [cell setNeedsLayout] устраняет эту проблему. Спасибо всем за вашу помощь!

4b9b3361

Ответ 1

Кажется, что просто установить текст ячейки недостаточно, чтобы он обновлялся. Пробовали ли вы поместить [cell setNeedsDisplay] после установки текста и посмотреть, что произойдет? Кстати, поскольку вы уже используете GCD для вычисления материала в фоновом режиме, вы должны попытаться вообще не выполнять какую-либо работу в главной очереди. Я бы написал, что часть кода больше похожа:

NSDictionary *data = [self timeForObject: [self.months objectAtIndex:indexPath.row]];
NSString *time      = [data objectForKey:@"Time"];
NSString *totalTime = [data objectForKey:@"Total Time"];
NSString *textLabel = [NSString stringWithFormat:@" %@ %@", time, totalTime];

dispatch_async(dispatch_get_main_queue(), ^{
    [[cell textLabel] setText:textLabel];
    [cell setNeedsDisplay];
});

Ответ 2

Кажется, вы обновляете ячейку в другом потоке (который не является основным потоком)

Попробуйте это при перезагрузке таблицы:

Objective-C

dispatch_async(dispatch_get_main_queue(), ^{
    [self.tableView reloadData];
});

Свифта

dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}

Ответ 3

Я предполагаю, что GCD запускает ваш блок в основном потоке с режимом цикла запуска по умолчанию. Попробуйте другой способ:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    [[cell textLabel] setFont: [UIFont systemFontOfSize: 32.0]];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSDictionary * data = [self timeForObject: [self.months objectAtIndex:indexPath.row]];
        NSString *time      = [data objectForKey:@"Time"];
        NSString *totalTime = [data objectForKey:@"Total Time"];
        NSString *textLabel  = [NSString stringWithFormat:@" %@ %@", time, totalTime];

        [cell performSelectorOnMainThread:@selector(setText:) withObject:textLabel waitUntilDone:NO modes:@[NSRunLoopCommonModes]]; //instead of using literals you could do something like this [NSArray arrayWithObject:NSRunLoopCommonModes];
    });

    return cell;
}

Ответ 4

Свифт 5

    DispatchQueue.main.async() {
        self.listView.reloadData()
    }