Вопрос по cocoa, objective-c – Данные не загружаются в UITableView, пока я не прокручиваю

52

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

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self performSelectorInBackground:@selector(fethchData) withObject:nil];


}


- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
self.listData = nil;
    self.plot=nil;
}


-(void) fethchData

{
    NSError *error = nil;
    NSURL *url=[[NSURL alloc] initWithString:@"http://www.website.com/"];
    NSString *strin=[[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

    HTMLParser *parser = [[HTMLParser alloc] initWithString:strin error:&error];

    if (error) {
        NSLog(@"Error: %@", error);
        return;
    }

    listData =[[NSMutableArray alloc] init];
    plot=[[NSMutableArray alloc] init];

    HTMLNode *bodyNode = [parser body];
    NSArray *contentNodes = [bodyNode findChildTags:@"p"];


    for (HTMLNode *inputNode in contentNodes) {
            [plot addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];    
        }


    NSArray *divNodes = [bodyNode findChildTags:@"h2"];

    for (HTMLNode *inputNode in divNodes) {

            [listData addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];          

        }
    }


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{

    static NSString *CellIdentifier = @"Cell";
    //here you check for PreCreated cell.
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    }

    //Fill the cells...  


    cell.textLabel.text = [listData objectAtIndex:indexPath.row];
    cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
    cell.textLabel.numberOfLines=6; 
    cell.textLabel.textColor=[UIColor colorWithHue:0.7 saturation:1 brightness:0.4 alpha:1];


    cell.detailTextLabel.text=[plot objectAtIndex:indexPath.row];
    cell.detailTextLabel.font=[UIFont systemFontOfSize:11];
    cell.detailTextLabel.numberOfLines=6;

    return cell;


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

Ваш Ответ

7   ответов
14

Для быстрой 3:

                self.tableView.reloadData()
            })

Для быстрого 2:

dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.tableView.reloadData()
            })
bro swift 3 работает хорошо !! ... Спасибо May Phyu
@ MayPhyu Всегда пожалуйста Hamid
129

Поместите это куда-нибудьосле успешной загрузки данн:

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

Это решает проблему вызова обновления GUI пока ты не в главной теме.

Этот код использует технологию GCD от Apple, чтобы принудительно запустить функцию перезагрузки данных в главном потоке. Узнайте больше о Руководство по программированию параллелизма для большего понимания (это довольно большое поле, так что его трудно объяснить в комментарии) В любом случае, это не очень рекомендуется, если вы не понимаете это хорошо, потому что это вызывает сбой программы в некоторых редких случаях.

Благодарность. Я поспешно переместил некоторые вещи и не понял, что моя загрузка данных была в другом потоке, и, следовательно, мои reloadData также. Спасибо, что помогли мне вернуться и проанализировать вещи. chadbag
Спасибо! Это просто решило действительно досадную ошибку, которая у меня была. Ian Spence
ОГРОМНАЯ ПОМОЩЬ! Благодарност Greg
@ Envil Не могли бы вы пролить свет на то, как это может привести к сбоям. Мое приложение случайно падает. Даже потратив много времени на отладку, я не могу исправить сбои. Abdurrahman Mubeen Ali
@ AbdurrahmanMubeenAli Вы должны создать новый вопрос и подробно его описать. Я не могу дать вам решение с вашим небольшим описанием. Envil
9

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

[tableView reloadData];

Так как это происходит синхронно, у вас должна быть такая функция, как

-(void) updateTable
{
    [tableView reloadData];
}

и после добавления данных в ваш вызов загрузки

[self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:NO];
Это говорит "неизвестный получатель tableView" Benjamen
Код приведен в качестве примера, я не знаю точную структуру вашего класса или макета представления. Дело в том, что вам нужно получить ссылку на ваше табличное представление (если ваш класс является экземпляром или подклассом UITableViewController, вы должны просто иметь self.tableView) и вызватьreloadData метод на нем Dan F
В UITabbleviewController это будет Self.tableView LavaSlider
Сейчас лучше, но мне все равно нужно дотронуться до tableView, чтобы загрузить данные. Раньше мне приходилось больше прокручивать. Спасибо, ребята, в любом случае. Benjamen
Я использовал это [self executeSelector: @selector (fethchData) withObject: nil afterDelay: 0]; в комбинации ваших примеров кодов. Benjamen
2

например

dispatch_async(dispatch_get_main_queue(), ^{
            [cell setNeedsDisplay];
            [cell.contentView addSubview:yourView];
        });
1

чтобы UITableView был полностью заполнен до появления контроллера представления. Сообщение Envil дало мне необходимую информацию, но мое решение оказалось другим.

Вот что я сделал (переделал, чтобы соответствовать контексту вопроса).

- (void)viewDidLoad {
    [super viewDidLoad];
    [self performSelectorInBackground:@selector(fethchData) withObject:nil];
}

- (void)viewWillAppear {
    [tableView reloadData];
}
1

Я использую статические ячейки, а reloadData вызывает неправильную загрузку, отображает только видимые ячейки и удаляет остальные. Что я заметил, так это то, что когда я прокручивал (у меня отрицательное значение) ячейки, которые были загружены правильно, я написал этот код, и он заработал, хотя я не хотел, чтобы он был таким.

Стреляй, если найдешь лучшее решение.

-(void)reloadTableView{
        CGPoint point = self.tableSettings.tableView.contentOffset;
        [self.tableSettings.tableView reloadData];

        [UIView animateWithDuration:.001f animations:^{
            [self.tableSettings.tableView setContentOffset:CGPointMake(point.x, -10)];
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:.001f animations:^{
                [self.tableSettings.tableView setContentOffset:point];
            } completion:^(BOOL finished) {

            }];
        }];
}
Это сработало для меня. Дайте мне знать, если вы выяснили актуальную проблему Pranav Raj
0

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

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

DispatchQueue.main.async(execute: { [weak weakSelf = self] () -> Void in
            weakSelf!.tableView.reloadData()
        })

Видеть:https: //developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID5

Это исправило мою проблему: DispatchQueue.main.async (execute: {[слабый weakCell = ячейка] () -> Void в weakCell! .ImageView! .Layer.cornerRadius = cell.imageView! imageView! .clipsToBounds = true}) user3590685

Похожие вопросы