UITableView reloadData занимает слишком много времени - PullRequest
2 голосов
/ 17 марта 2012

Я использую TBXML + HTTP для получения данных XML с веб-сайта. Что я хочу сделать, это заполнить UITableView обработанными данными. Я создал NSMutableArray, который содержит все записи и, насколько это возможно, все работает нормально. Проблема заключается в том, что после успешного извлечения данных с сервера и сохранения их в массиве я пытаюсь обновить таблицу для отображения данных, используя reloadData.

Заполнение таблицы 20 строками занимает около 5 секунд. Странная часть в том, что выборка происходит очень быстро, поэтому данные доступны сразу. Я не понимаю, что занимает так много времени. Вот некоторая информация из журнала:

2012-03-17 18:46:01.045 MakeMyApp[4571:207] numberOfSectionsInTableView: 1
2012-03-17 18:46:01.047 MakeMyApp[4571:207] numberOfRowsInSection: 0
2012-03-17 18:46:01.244 MakeMyApp[4571:1f03] numberOfSectionsInTableView: 1
2012-03-17 18:46:01.245 MakeMyApp[4571:1f03] numberOfRowsInSection: 20
2012-03-17 18:46:01.245 MakeMyApp[4571:1f03] Ok, I'm done. 20 objects in the array.
2012-03-17 18:46:01.246 MakeMyApp[4571:1f03] Finished XML processing.
2012-03-17 18:46:06.197 MakeMyApp[4571:1f03] cellForRowAtIndexPath:

Как видите, она запускает пару numberOfSectionsInTableView: / numberOfRowsInSection: два раза: первый - когда загружается представление, второй - когда я [self.tableView reloadData];

Вы видите, что менее чем за секунду массив заполняется 20 объектами, и вся работа по обработке XML выполняется. Как cellForRowAtIndexPath: срабатывает только через 5 секунд?

Вот некоторые части кода, которые могут помочь найти проблему:

- (void)createRequestFromXMLElement:(TBXMLElement *)element {
    // Let's extract all the information of the request
    int requestId = [[TBXML valueOfAttributeNamed:@"i" forElement:element] intValue];

    TBXMLElement *descriptionElement = [TBXML childElementNamed:@"d" parentElement:element];
    NSString *description = [TBXML textForElement:descriptionElement];

    TBXMLElement *statusElement = [TBXML childElementNamed:@"s" parentElement:element];
    int status = [[TBXML textForElement:statusElement] intValue];

    TBXMLElement *votesCountElement = [TBXML childElementNamed:@"v" parentElement:element];
    int votesCount = [[TBXML textForElement:votesCountElement] intValue];    

    // Creating the Request custom object
    Request *request = [[Request alloc] init];

    request.requestId = requestId;
    request.description = description;
    request.status = status;
    request.votes_count = votesCount;

    [requestsArray addObject:request];
}


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

    appListCell *cell = (appListCell *)[tableView dequeueReusableCellWithIdentifier:@"appListCell"];

    Request *request = [requestsArray objectAtIndex:indexPath.row];

    cell.appIdLabel.text = [NSString stringWithFormat:@"#%d", request.requestId];
    cell.appTextLabel.text = request.description;
    cell.appVotesLabel.text = [NSString stringWithFormat:@"%d votes", request.votes_count];

    return cell;
}

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

РЕДАКТИРОВАТЬ:

- (void)traverseXMLAppRequests:(TBXMLElement *)element {
    int requestCount = 0;
    TBXMLElement *requestElement = element->firstChild;

    // Do we have elements inside <re>?
    if ((requestElement = (element->firstChild))) {
        while (requestElement) {
            [self createRequestFromXMLElement:requestElement];

            requestCount++;

            requestElement = [TBXML nextSiblingNamed:@"r" searchFromElement:requestElement];
        }
    }

    [self.tableView reloadData];   

    NSLog(@"Ok, I'm done. %d objects in the array.", [requestsArray count]);

}

РЕДАКТИРОВАТЬ 2: Я пытался получить информацию только 1 строки вместо 20, и задержка точно такая же.

Ответы [ 3 ]

16 голосов
/ 11 ноября 2014

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

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

Попробуйте изменить вызов reloadData на:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.tableView reloadData];
});
8 голосов
/ 26 мая 2015

Вы звоните reloadData в потоке, отличном от mainThread

Обязательно перезагрузите данные tableView в основном потоке, как показано ниже:

OBJ-C:

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

Swift 3:

DispatchQueue.main.async {
   self.tableView.reloadData()
}
0 голосов
/ 20 марта 2012

Куда звонят:

- (void)createRequestFromXMLElement:(TBXMLElement *)element

?Похоже, вы делаете 20 веб-запросов, чтобы получить содержимое этого файла.Это определенно замедлит работу (в отличие от одного запроса на получение всего XML-файла и его локального анализа).

Можете ли вы опубликовать весь код VC?

...