Как отобразить изображение заполнителя, когда в моем UITableView еще нет данных? - PullRequest
1 голос
/ 19 мая 2009

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

Однако, когда пользователь сначала загружает приложение (до того, как они создали какие-либо данные), я хотел бы отобразить вместо пустой таблицы фоновое изображение (со стрелкой, указывающей на кнопка «Добавить запись» (панель навигации). Как только пользователь добавил свою первую запись, вместо нее отображается табличное представление. Я видел множество приложений, делающих это - единственный пример, о котором я могу подумать в настоящее время, это Cha-Ching, прежде чем вы настроите какой-либо бюджет и т.д. Хотя я не могу понять, как это сделать.

Сначала я добавил навигационный контроллер в xib главного окна, rootViewController которого был пользовательским viewcontroller / xib. Этот rootViewController содержал фоновое изображение со скрытым табличным представлением над ним и настраиваемый контроллер табличного представления, который управлял табличным представлением. Казалось, что это работает просто отлично, и если есть данные, они загружаются и отображаются в таблице. Однако, если бы я прокрутил данные за пределами экрана, приложение зависло бы с этой ошибкой:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'*** -[UITextEffectsWindow tableView:cellForRowAtIndexPath:]: unrecognized selector sent to instance 0xd2d130'

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

Если есть гораздо более простой / более простой способ сделать это, я был бы очень признателен, если бы кто-то мог объяснить это. Как бы вы это сделали?

Заранее спасибо.

Ответы [ 5 ]

1 голос
/ 08 февраля 2011

Для этого я использую следующий контроллер вместо UITableViewController. Он автоматически разместит представление над таблицей, когда оно пустое, и удалит его, когда заполнится.

Просто позвоните [self reloadData] вместо [self.tableView reloadData], чтобы он мог проверить, не стала ли таблица пустой.

В вашем подклассе реализуйте функцию makeEmptyOverlayView, которая создаст представление для отображения над пустой таблицей.

@interface MyTableViewController : UITableViewController
{
      BOOL hasAppeared;
      BOOL scrollWasEnabled;
      UIView *emptyOverlay;
}

- (void) reloadData;
- (void) checkEmpty;

@end

@implementation MyTableViewController

- (void)viewWillAppear:(BOOL)animated
{
   [self reloadData];
   [super viewWillAppear: animated];
}

- (void)viewDidAppear:(BOOL)animated
{
   hasAppeared = YES;

   [super viewDidAppear: animated];

   [self checkEmpty];
}

- (void)viewDidUnload
{
   if (emptyOverlay)
   {
      self.tableView.scrollEnabled = scrollWasEnabled;
      [emptyOverlay removeFromSuperview];
      emptyOverlay = nil;
   }
}

- (void) reloadData
{
   [self.tableView reloadData];

   if (hasAppeared &&
       [self respondsToSelector: @selector(makeEmptyOverlayView)])
      [self checkEmpty];
}

- (void) checkEmpty
{
   BOOL isEmpty(YES);

   id<UITableViewDataSource> src(self.tableView.dataSource);
   NSInteger sections(1);
   if ([src respondsToSelector: @selector(numberOfSectionsInTableView:)])
      sections = [src numberOfSectionsInTableView: self.tableView];
   for (int i(0); i<sections; ++i)
   {
      NSInteger rows([src tableView: self.tableView numberOfRowsInSection: i]);
      if (rows)
         isEmpty = NO;
   }

   if (!isEmpty != !emptyOverlay)
   {
      if (isEmpty)
      {
         scrollWasEnabled = self.tableView.scrollEnabled;
         self.tableView.scrollEnabled = NO;
         emptyOverlay = [self makeEmptyOverlayView];
         [self.tableView addSubview: emptyOverlay];
         [emptyOverlay release];
      }
      else
      {
         self.tableView.scrollEnabled = scrollWasEnabled;
         [emptyOverlay removeFromSuperview];
         emptyOverlay = nil;
      }
   }
   else if (isEmpty)
   {
      // Make sure it is still above all siblings.
      [emptyOverlay retain];
      [emptyOverlay removeFromSuperview];
      [self.tableView addSubview: emptyOverlay];
      [emptyOverlay release];
   }
}

@end
1 голос
/ 04 января 2010

Чтобы добиться этого, используя подкласс UITableViewController в качестве моего единственного представления (в пределах UINavigationController согласно шаблону Apple), я использовал следующий подход:

  1. Создайте UIView размера моего tableView в XIB, который содержит ваш UITableViewController и tableView.

  2. Добавьте набор ImageView с моим изображением-заполнителем в UIView.

  3. Подключите UIView как IBOutlet (в приведенном ниже примере кода я назвал его emptyTableView)

  4. Когда пришло время показать заполнитель из подкласса UITableViewController:

    [self.tableView addSubView: emptyTableView]; [self.tableView setScrollEnabled: FALSE];

Отключение прокрутки необходимо, в противном случае пользователь сможет перемещать изображение-заполнитель вверх и вниз. Просто не забудьте включить его, как только пользователь добавляет элемент.

  1. Для удаления вида изображения

    [emptyTableView removeFromSuperview];

1 голос
/ 19 мая 2009

Вот одно решение, которым я доволен до сих пор.

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

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

Мне нравится ваш метод использования изображения, хотя. Если все сделано правильно, это может сэкономить вам некоторую работу, если вам не нужно локализовать строку, как я в настоящее время.

0 голосов
/ 21 мая 2009

Итак, чтобы решить эту проблему, я сделал, как обсуждалось в комментариях выше:

Я создал обычный подкласс UIViewController, который содержал UIImageView и UITableView. ViewController соответствует протоколам UITableViewDelegate и UITableViewDatasource и следит за tableView. Класс viewController просто показывает или скрывает imageView в зависимости от того, доступны ли данные.

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

Спасибо за помощь!

0 голосов
/ 19 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...