Показывать пользовательскую метку, когда нет данных для tableView

В рассматриваемом приложении пользователи могут отмечать элементы как избранные. Когда у пользователя нет сохраненных избранных, я хотел бы уведомить их об этом факте (в основном я ненавижу идею пустого tableView).

Мой numberOfRowsInSection равен нулю, когда нет элементов, отмеченных пользователем как избранное. Я хотел бы установить cell.textLabel.text = @"У вас нет избранного", но когда для таблицы нет элементов, cellForRowAtIndexPath не вызывается.

Я мог бы протестировать numberOfRowsInSection, чтобы получить результат, когда он встречает 0, а затем проверить 1 строку в cellForRowAtIndexPath, а затем вставить пользовательский текст, но что, если у них есть только один любимый?

ОБНОВИТЬ

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

Я получаю эту ошибку, когда удаляю ячейку, когда в таблице есть только одна ячейка:

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UITableView.m:976 Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted). with userInfo (null)

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

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFBatchFaultingArray objectAtIndex:]: index (0) beyond bounds (0)'

Вот соответствующий код:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    id <NSFetchedResultsSectionInfo> sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];

    if ([sectionInfo numberOfObjects]==0) {
        return 1;
    } else {
        return [sectionInfo numberOfObjects];
    }
} 

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

if ([[_fetchedResultsController sections] objectAtIndex:0]==0) {
    cell.textLabel.text = @"You have no favorites";
} else {
    Shows *show = [_fetchedResultsController objectAtIndexPath:indexPath];

    cell.textLabel.text = show.ShowsToSerials.serialName;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", show.showTitle];
}
}

person Michael Morrison    schedule 30.01.2011    source источник


Ответы (3)


1) В моих собственных приложениях для iOS я создаю подпредставление с UILabel в нем, говоря «Нет результатов». Когда numberOfSectionsInTableView равен нулю, я добавляю подпредставление в табличное представление. Когда это != ноль, я удаляю его. Это, конечно, требует сохранения подпредставления в памяти как сохраненного объекта, чтобы вы могли его удалить.

2) Если вы хотите сделать одну ячейку, как вы несколько упомянули: когда numberOfSectionsInTableView равно нулю, верните 1. Затем в numberOfRowsInSection также верните 1. В cellForRowAtIndexPath проверьте как numberOfSectionsInTableView, так и numberOfRowsInSection, и если они ДОЛЖНЫ быть равны нулю (ведь вы вернули 1), то отобразите любое сообщение.

Решение 1 требует сохранения переменной для хранения подпредставления, но это более короткий и чистый код, и я считаю, что он менее интенсивно использует ЦП (но это не вызовет каких-либо значительных проблем с производительностью).

Редактировать, чтобы включить код. На самом деле это немного отличалось от того, что я думал, но в основном то же самое. Очевидно, здесь есть вещи, которые нужно изменить, чтобы они соответствовали вашему коду и вкусу.

(Обязательно объявите UIView *nomatchesView; в .h)

- (void)viewDidLoad{

        nomatchesView = [[UIView alloc] initWithFrame:self.view.frame];
        nomatchesView.backgroundColor = [UIColor clearColor];

        UILabel *matchesLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,320,320)];
        matchesLabel.font = [UIFont boldSystemFontOfSize:18];
        matchesLabel.minimumFontSize = 12.0f;
        matchesLabel.numberOfLines = 1;
        matchesLabel.lineBreakMode = UILineBreakModeWordWrap;
        matchesLabel.shadowColor = [UIColor lightTextColor];
        matchesLabel.textColor = [UIColor darkGrayColor];
        matchesLabel.shadowOffset = CGSizeMake(0, 1);
        matchesLabel.backgroundColor = [UIColor clearColor];
        matchesLabel.textAlignment =  UITextAlignmentCenter;

        //Here is the text for when there are no results
        matchesLabel.text = @"No Matches";


        nomatchesView.hidden = YES;
        [nomatchesView addSubview:matchesLabel];
        [self.tableView insertSubview:nomatchesView belowSubview:self.tableView];
    }



    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        //If there is no table data, unhide the "No matches" view
        if([data count] == 0 ){
        nomatchesView.hidden = NO;
        } else {
        nomatchesView.hidden = YES;
        }

        return [data count];
    }
person Daniel Amitay    schedule 30.01.2011
comment
Даниэль. Еще раз спасибо за ваш код. Просто вопрос по управлению памятью. Я освобождаю вид в Dealloc (это лучше?), но где я должен освобождать метку? - person Michael Morrison; 09.06.2011
comment
У меня есть представление, и все выпущено в дело. Я не верю, что у меня что-то течет. - person Daniel Amitay; 09.06.2011

Лично я бы сделал следующее. Как вы сами сказали, в методе numberOfRowsInSection вы должны проверить количество вашего источника данных tableView, если его 0, вы должны вернуть 1, чтобы отобразить 1 ячейку, которую вы хотите.

Затем в cellForRowAtIndexPath вы должны снова проверить счетчик, если он возвращает 0, вы знаете, что табличное представление пытается нарисовать ваше «В настоящее время у вас нет избранных», и вы можете установить текст.

person Antwan van Houdt    schedule 30.01.2011

Как упоминалось в приведенной ниже ссылке, это легко сделать, если мы создадим метку и установим ее в качестве фонового представления для UITableView, как показано ниже. http://www.appcoda.com/pull-to-refresh-uitableview-empty/

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    if (data) {

        self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        return 1;

    } else {

        // Display a message when the table is empty
        UILabel *messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];

        messageLabel.text = @"No data is currently available. Please pull down to refresh.";
        messageLabel.textColor = [UIColor blackColor];
        messageLabel.numberOfLines = 0;
        messageLabel.textAlignment = NSTextAlignmentCenter;
        messageLabel.font = [UIFont fontWithName:@"Palatino-Italic" size:20];
        [messageLabel sizeToFit];

        self.tableView.backgroundView = messageLabel;
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

    }

    return 0;
}
person Koti Tummala    schedule 03.03.2015