Настройка стиля UITableViewCell при использовании iOS 6 UITableView dequeueReusableCellWithIdentifier:forIndexPath:

Я пытаюсь понять, как установить UITableViewCellStyle при использовании новых методов в iOS 6 для UITableView,

Ранее при создании UITableViewCell Я бы поменял UITableViewCellStyle enum для создания различных типов ячеек по умолчанию при вызове initWithStyle: но из того, что я могу собрать, это уже не так.

Документация Apple для UITableView состояния:

Возвращаемое значение: объект UITableViewCell со связанным идентификатором повторного использования. Этот метод всегда возвращает действительную ячейку.

Обсуждение: Из соображений производительности источник данных табличного представления обычно должен повторно использовать объекты UITableViewCell, когда он присваивает ячейки строкам в своем tableView:cellForRowAtIndexPath: метод. Табличное представление поддерживает очередь или список объектов UITableViewCell, которые источник данных отметил для повторного использования. Вызовите этот метод из объекта источника данных, когда вас попросят предоставить новую ячейку для табличного представления. Этот метод удаляет существующую ячейку, если она доступна, или создает новую на основе ранее зарегистрированного файла класса или пера.

Важное замечание: Необходимо зарегистрировать файл класса или пера, используя registerNib: forCellReuseIdentifier: или registerClass: forCellReuseIdentifier: метод перед вызовом этого метода.

Если вы зарегистрировали класс для указанного идентификатора и необходимо создать новую ячейку, этот метод инициализирует ячейку, вызывая ее метод initWithStyle: reuseIdentifier:. Для ячеек на основе пера этот метод загружает объект ячейки из предоставленного файла пера. Если существующая ячейка была доступна для повторного использования, этот метод вместо этого вызывает метод prepareForReuse ячейки.

Вот так мой новый cellForRowAtIndexPath заботится о реализации новых методов:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cell_identifier";

    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellIdentifier];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    return cell;
}

Код, который у меня есть, работает нормально, но всегда возвращает стиль по умолчанию. Как я могу изменить это, чтобы я мог создавать ячейки с другими стилями, такими как UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2 а также UITableViewCellStyleSubtitle?

Я не хочу подкласс UITableViewCellЯ просто хочу изменить тип по умолчанию, как я мог сделать до iOS 6. Кажется странным, что Apple предоставит улучшенные методы, но с минимальной документацией для поддержки их реализации.

Кто-нибудь справился с этим или столкнулся с подобной проблемой? Я изо всех сил пытаюсь найти какую-либо разумную информацию вообще.

6 ответов

Решение

Я знаю, что вы сказали, что не хотите создавать подкласс, но это выглядит неизбежно. Основываясь на коде сборки во время тестирования в симуляторе iOS 6.0, UITableView создает новые экземпляры UITableViewCell (или его подклассы), выполняя

[[<RegisteredClass> alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:<ReuseIdentifier>]

Другими словами, стиль отправлен (UITableViewCellStyleDefault) представляется жестко закодированным. Чтобы обойти это, вам нужно создать подкласс, который переопределяет инициализатор по умолчанию initWithStyle:reuseIdentifier: и передает стиль, который вы хотите использовать:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    // ignore the style argument, use our own to override
    self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
    if (self) {
        // If you need any further customization
    }
    return self;
}

Кроме того, может быть лучше отправить registerClass:forCellReuseIdentifier: в viewDidLoadвместо того, чтобы делать это каждый раз, когда запрашивается ячейка:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:<RegisteredClass> forCellReuseIdentifier:<ReuseIdentifier>];
}

dequeueReusableCellWithIdentifier не считается устаревшим, поэтому вы не обязаны использовать новый dequeueReusableCellWithIdentifier:forIndexPath:,

Используйте новый способ вместе с соответствующим методом регистра (в viewDidLoad), если вы используете пользовательский класс ячейки, но используйте старый способ, если вы хотите использовать одно из перечислений UITableViewCellStyle.

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

  1. В представлении Раскадровка выберите ячейку прототипа ячейки табличного представления (в табличном представлении)
  2. В представлении "Утилиты" в инспекторе атрибутов измените значение стиля.
  3. (Необязательно) Измените другие значения, такие как Выбор и Аксессуар

Новая iOS 6.0 dequeueReusableCellWithIdentifier:forIndexPath: использует эти значения при выделении новых ячеек и их возвращении. (Проверено на компиляции iOS 6.0 с использованием Xcode 4.5.2)

Еще одна альтернатива, которая сохраняет один файл, - это создать перо и использовать registerNib:forCellReuseIdentifier: вместо.

Сделать Nib очень просто: создайте новый.xib-файл в Интерфейсном Разработчике. Удалить вид по умолчанию. Добавьте объект ячейки табличного представления. С помощью инспектора атрибутов измените стиль ячейки. (Здесь у вас также есть возможность дополнительно настроить ячейку, настроив другие атрибуты.)

Тогда в вашем табличном представлении контроллера viewDidLoad вызов метода что-то вроде:

[self.tableView registerNib:[UINib nibWithNibName:@"StyleSubtitleTableCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"Cell"];

Болот ответ правильный. Все просто, и вам не нужно создавать какой-либо файл XIB.

Я просто хотел обновить его ответ для тех, кто делает это, используя Swift вместо Objective-C:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: .value1, reuseIdentifier: reuseIdentifier)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

Мое решение этого заключается в том, чтобы позвонить initWithStyle: reuseIdentifier: после того как я получил его с помощью [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath], В конце концов, init это просто другой селектор, и компилятор не ограничивает вызов его для уже инициализированного объекта. Однако он будет жаловаться на то, что не использует результат вызова init, поэтому я делаю:

UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath];
cell = [cell initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellId"];

Я полагаю, это не будет работать в Swift...

Другие вопросы по тегам