UITableViewCell: использование стандартных ячеек в iOS-разработке

IT-копирайтер
Время чтения: 13 минут
Один из ключевых моментов при создании любого iOS-приложения — работа с таблицами и ячейками, из которых они строятся. Существует несколько способов создания ячеек таблицы: с помощью стандартных стилей, используя стандартный класс UITableViewCell, и с помощью пользовательских стилей — наследование от UITableViewCell. Использование пользовательских ячеек позволяет создавать красивые и удобные интерфейсы, но разработчики часто забывают, что во многих случаях можно без потерь обойтись стандартными стилями. О преимуществах работы со стандартными ячейкам — сегодняшняя статья.
Наполнение ячеек элементами, созданными непосредственно в методе делегата таблицы, в статье не рассмотрено. Отметим только, что использование этого метода либо затрудняет доступ к элементам и делает его дольше, либо заставляет нас создавать элементы ячейки заново, что долго и не практично.
Использование стандартной ячейки:
- (UITableViewCell *)tableView:(UITableView *)curTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; { NSString *cellIdentifier = @"defaultCellIdentifier"; UITableViewCell *cell = [curTableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; } cell.textLabel.text = @"Some text"; return cell; }
Использование пользовательской ячейки, описанной в классе TableViewCellDefault:
- (UITableViewCell *)tableView:(UITableView *)curTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; { NSString *cellIdentifier = @"defaultCellIdentifier"; myTableViewCell *cell = (myTableViewCell *)[curTableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = (TableViewCellDefault *)[[[NSBundle mainBundle] loadNibNamed:@"TableViewCellDefault" owner:self options:nil] lastObject]; } cell.textLabel.text = @"Some text"; return cell; }
Описание класса ячейки:
.h файл #import @interface myTableViewCell : UITableViewCell @property (nonatomic, retain) IBOutlet UILabel *textLabel; @property (nonatomic, retain) IBOutlet UIImageView *myImageView; @property (nonatomic, retain) IBOutlet UIButton *myAccessoryButton; @end .m файл #import "myTableViewCell.h" @implementation myTableViewCell @synthesize textLabel; @synthesize myImageView; @synthesize myAccessoryButton; - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { } return self; } - (void)dealloc { self.textLabel = nil; self.myImageView = nil; self.myAccessoryButton = nil; [super dealloc]; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; } @end
Стандартные варианты ячеек
Рассмотрим общий вид ячейки.
Все стили ячеек имеют следующие поля:
- imageView — поле картинки ячейки (если картинка не задана — поле отсутствует);
- accessoryView, которому можно назначить произвольный вид или установить стандартный вид через cell.accessoryType (поле accessoryView отсутствует, если не задано или если задано cell.accessoryType = UITableViewCellAccessoryNone);
- contentView, видом которого и различаются ячейки.
Также все ячейки имеют фоновое изображение — backgroundView и фоновое изображение при выделении — selectedBackgroundView. При использовании пользовательских ячеек все поля остаются, но поле contentView растягивается на всю ширину ячейки, что делает неудобным использование imageView и accessoyView.
Стандартные виды accessoryView
Пример ячейки UITableViewCellStyleDefault:
1. cell.accessoryType = UITableViewCellAccessoryCheckmark
2. cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton
В данном случае accessoryView является кнопкой, которая может быть нажата без выбора ячейки, соответственно выбор ячейки и нажатия accessoryView независимые события. Нажатие accessoryView вызывает метод делегата таблицы
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath,
в который автоматически передается значение indexPath той ячейки, в которой был нажат accessoryView. Если данный accessoryView подходит по дизайну и по смыслу его также можно использовать вместе в пользовательскими ячейкам.
3. cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator
Ниже рассмотрены стандартные типы ячеек и примеры их реализации.
UITableViewCellStyleDefault
Вид contentView:
- (UITableViewCell *)tableView:(UITableView *)curTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; { NSString *cellIdentifier = @"сellIdentifier"; UITableViewCell *cell = [curTableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; cell.textLabel.textColor = [UIColor whiteColor]; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]] autorelease]; cell.selectedBackgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"selectedBackground.png"]] autorelease]; cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; } cell.textLabel.text = [NSString stringWithFormat:@"Simple text %i", indexPath.row]; cell.imageView.image = [UIImage imageNamed:@"smile.png"]; return cell; }
UITableViewCellStyleValue1
contentView:
- (UITableViewCell *)tableView:(UITableView *)curTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; { NSString *cellIdentifier = @"сellIdentifier"; UITableViewCell *cell = [curTableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; cell.textLabel.textColor = [UIColor whiteColor]; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.textColor = [UIColor whiteColor]; cell.detailTextLabel.backgroundColor = [UIColor clearColor]; cell.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]] autorelease]; cell.selectedBackgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"selectedBackground.png"]] autorelease]; cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; } cell.textLabel.text = [NSString stringWithFormat:@"Simple text %i", indexPath.row]; cell.detailTextLabel.text = [NSString stringWithFormat:@"detail text %i", indexPath.row]; cell.imageView.image = [UIImage imageNamed:@"smile.png"]; return cell; }
UITableViewCellStyleValue2
У UITableViewCellStyleValue2 отсутствует поле imageView, но вместо него можно использовать произвольный вид accessoryView
contentView:
- (UITableViewCell *)tableView:(UITableView *)curTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; { NSString *cellIdentifier = @"сellIdentifier"; UITableViewCell *cell = [curTableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; cell.textLabel.textColor = [UIColor whiteColor]; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.textColor = [UIColor whiteColor]; cell.detailTextLabel.backgroundColor = [UIColor clearColor]; cell.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]] autorelease]; cell.selectedBackgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"selectedBackground.png"]] autorelease]; cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; } cell.textLabel.text = [NSString stringWithFormat:@"Simple text %i", indexPath.row]; cell.detailTextLabel.text = [NSString stringWithFormat:@"detail text %i", indexPath.row]; cell.imageView.image = [UIImage imageNamed:@"smile.png"]; return cell; }
UITableViewCellStyleSubtitle
contentView:
- (UITableViewCell *)tableView:(UITableView *)curTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; { NSString *cellIdentifier = @"сellIdentifier"; UITableViewCell *cell = [curTableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; cell.textLabel.textColor = [UIColor whiteColor]; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.textColor = [UIColor whiteColor]; cell.detailTextLabel.backgroundColor = [UIColor clearColor]; cell.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]] autorelease]; cell.selectedBackgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"selectedBackground.png"]] autorelease]; cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; } cell.textLabel.text = [NSString stringWithFormat:@"Simple text %i", indexPath.row]; cell.detailTextLabel.text = [NSString stringWithFormat:@"detail text %i", indexPath.row]; cell.imageView.image = [UIImage imageNamed:@"smile.png"]; return cell; }
Теперь сравним скорости создания и повторного использования (когда все ячейки уже созданы) стандартных и пользовательских ячеек. Сравнение будем проводить на плеере iPod touch 4 Gen.
Обозначения
- Reuse — время в миллисекундах на повторное использование ячейки методом dequeueReusableCellWithIdentifier и установку новых значений свойств ячейки.
- Create — время в миллисекундах, затраченное на создание ячейки, если вышеописанный метод вернул пустую ячейку.
UITableViewCellStyleDefault с заданием различных свойств и пользовательская ячейка такого же вида.
Результаты для стандартной ячейки вида UITableViewCellStyleDefault:
Результаты для пользовательской ячейки вида UITableViewCellStyleDefault:
Результаты для стандартной ячейки вида UITableViewCellStyleSubtitle:
Результаты для пользовательской ячейки вида UITableViewCellStyleSubtitle:
Вывод
Как вы увидели, повторное использование ячейки занимает примерно одно и то же время во всех тестах, так как время этого механизма не зависит от самих ячеек, а время на установку параметров в обоих случаях одинаковое. Хотя создание таблицы на 3-4 миллисекунды для каждой ячейки не сыграет большой роли, основное преимущество использования стандартных ячеек заключается в отсутствии необходимости добавления собственных классов, а также гарантии поддержки ячеек как стандартных элементов в будущих версиях iOS.
Комментарии