UITableView не обновляется должным образом после изменения dataSource

У меня есть UITableView с несколькими источниками данных. Это связано с тем, что мне нужно переключать данные с помощью UISegmentedControl, и если я добавлю их в качестве подзонов, я не могу использовать statusBar для прокрутки вверх и т.д.

Сначала я показываю экран входа:

self.tableView.dataSource = loginTableView;
self.tableView.delegate = loginTableView;
[self.tableView reloadData];

Затем, как только пользователь вошел в систему, я делаю следующее, чтобы изменить на индекс: 1 сегмента segmentControler, который является их профилем:

self.tableView.dataSource = profileTableView;
self.tableView.delegate = profileTableView;
[self.tableView reloadData];

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

Есть ли другой способ изменить источник данных для UITableView?

спасибо

Ответы

Ответ 1

Не уверен, почему это происходит из кода, который вы опубликовали.

Вместо того, чтобы изменять делегат и источник данных, замените все, что представляет ivar, на отображаемые данные:

- (NSArray*)tableData{

    if(showingLogin)
        return self.loginData;

    return self.profileData;
}

Теперь у вас есть только 1 экземпляр UITableViewController, но BOOL сообщит вам, какой источник данных использовать.

Ответ 2

У меня была такая же проблема. Мое решение состояло в том, чтобы сделать tableView скрытым, изменить его источник, перезагрузить данные и снова отобразить таблицу.

Пример в С# (MonoTouch):

tableView.Hidden = true;
tableView.Source = newTableViewSource;
tableView.ReloadData();
tableView.Hidden = false;

Ответ 3

В представлении таблицы происходит кэширование ячеек, которые он использует для отображения ваших данных. Поэтому, если вы меняете источник данных, вы также должны проверить, что ваш - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) метод indexPath обновляет все ячейки до правильных новых значений.

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

- (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];
        cell.frame = CGRectZero;
        cell.textLabel.font = //Set font;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.textLabel.text = @"My Text for this cell"; // <==== Not good! Move it out of this if block
    }
    // Set cell text here
}

Простейшим решением, которое я нашел для этой проблемы, является просто создание String, который вы используете для создания ячейки (CellIdentifier) ​​в зависимости от источника данных. В этом случае вы не смешиваете ячейку разных типов контента (и это также помогает вам, если ячейки должны иметь другой вид в зависимости от режима).

Ответ 4

У меня была эта проблема, оказалось, что это потому, что мои CellIdentifiers были одинаковыми...

static NSString *CellIdentifier = @"Cell";

Измените один из них и расположение ячеек правильно

static NSString *CellIdentifier2 = @"Cell2";

Ответ 5

Ничего себе, этот причудливый.

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

Ответ 6

У меня такая же проблема, и вам нужно использовать другой идентификатор ячейки внутри - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.

if (self.segmentedControl.selectedSegmentIndex == 0) {
    self.cellIdentifier = @"segmentOne";
} else {
    caseAtIndexPath = [self.awaitingReviewCaseList caseAtIndex:indexPath.row];
    self.cellIdentifier = @"segmentTwo";
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];