UITableView: viewForHeaderInSection: не вызывается во время reloadData:

127

Я установил tableview с правильными связями делегата и источника данных .. метод reloadData вызывает источник данных и методы делегата, за исключением viewForHeaderInSection:.

Почему это так?

inforeqd
источник
30
Является ли heightForHeaderInSection:реализован?
7usam
Вы установили значение для TableView sectionHeaderHeight?
Картер Медлин,

Ответы:

256

Использование tableView:viewForHeaderInSection:требует, чтобы вы также реализовали tableView:heightForHeaderInSection:. Это должно вернуть соответствующую ненулевую высоту заголовка. Также убедитесь, что вы также не реализуете tableView:titleForHeaderInSection:. Вы должны использовать только одно или другое ( viewForHeaderили titleForHeader).

rmaddy
источник
3
Убедитесь, что в подписи метода нет опечатки. Одна неверная буква будет означать, что его не назовут. Проверьте и случай. Также убедитесь, что вы возвращаете 0 из numberOfSections.
rmaddy
все правильно и правильно компилируется .. проблема, которую я хотел понять, связана со временем, когда вызывается метод .. tableView: viewForHeaderInSection вызывается, когда таблица собирается отображаться, а не как часть синхронного выполнения [ tableview reloadData]
inforeqd
@maddy OMG Спасибо, это так глупо с моей стороны, я создал свои экземпляры, но не добавил в свой массив
Happiehappie
4
Вы можете получить и то, и другое. viewForHeaderInSection: будет иметь приоритет над titleForHeaderInSection: единственное требование - вы установите в представлении таблицы значение EstimatedSectionHeaderHeight, отличное от 0, иначе viewForHeaderInSection: никогда не будет вызван
romrom
Добавление к комментарию @romrom: если вы реализовали и titleForHeaderInSection:и, viewForHeaderInSection:и представление, возвращаемое из последнего, является подклассом, UITableViewHeaderFooterViewтогда textLabel.textоно автоматически устанавливается на версию titleForHeaderInSection:строки с заглавными буквами. Чтобы предотвратить такое поведение, либо не реализуйте, titleForHeaderInSection:либо используйте настраиваемую метку вместо унаследованной textLabel.
Ортвин Генц
40

Хитрость в том, что эти два метода принадлежат разным UITableViewпротоколам: tableView:titleForHeaderInSection:это UITableViewDataSourceметод протокола, которому tableView:viewForHeaderInSectionпринадлежит UITableViewDelegate.

Это значит:

  • Если вы реализуете методы, но назначаете себя только как dataSourceдля UITableView, ваша tableView:viewForHeaderInSectionреализация будет проигнорирована.

  • tableView:viewForHeaderInSectionимеет более высокий приоритет. Если вы реализуете оба метода и назначите себя как the, так dataSourceи как delegateдля UITableView, вы вернете представления для заголовков разделов, но ваши tableView:titleForHeaderInSection:будут проигнорированы.

Я тоже пробовал удалить tableView:heightForHeaderInSection:; он работал нормально и, похоже, не повлиял на описанные выше процедуры. Но в документации написано, что это необходимо для tableView:viewForHeaderInSectionкорректной работы; так что на всякий случай разумно реализовать и это.

Юнус Недим Мехел
источник
6
Вы сделали мой день!!! Забыл назначить UITableViewDelegateна self, потому что я думал, что tableView:viewForHeaderInSectionэто UITableViewDataSourceметод. Спасибо!
denis631
1
«tableView: viewForHeaderInSection» не имеет значения. Что важно, так это как- то вернуть высоту. Вы можете добиться этого с помощью 1. оценки, 2. жестко запрограммированного значения или 3. a, titleForHeaderимеющего внутренний размер. Внутренний размер рассчитывается на основе семейства шрифтов и размера.
Honey
28

@rmaddy имеет искажен правило, в два раза: на самом деле, tableView:viewForHeaderInSection:вовсе не требует , чтобы вы также осуществить tableView:heightForHeaderInSection:, а также он прекрасно подходит для вызова как titleForHeaderи viewForHeader. Правильно сформулирую правило для записи:

Правило состоит в том, что viewForHeaderон не будет вызываться, если вы каким-то образом не укажете высоту заголовка. Вы можете сделать это в любой комбинации из трех способов:

  • Реализовать tableView:heightForHeaderInSection:.

  • Накрыть на стол sectionHeaderHeight.

  • Вызов titleForHeader(это каким-то образом дает заголовку высоту по умолчанию, если в противном случае у него ее нет).

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

матовый
источник
Из документации tableView:viewForHeaderInSection:: «Этот метод работает правильно, только если tableView:heightForHeaderInSection:он также реализован».
rmaddy 02
1
Хорошо. Что говорят документы, говорят они. А теперь поэкспериментируйте. Факты таковы, как я сказал.
Мэтт
И как вы можете иметь как titleForHeaderInSectionи viewForHeaderInSection? Табличное представление вызовет только один из двух (я забыл, какой в ​​данный момент имеет приоритет).
rmaddy 02
1
На самом деле есть еще одна часть головоломки, которая иногда viewForHeader вызывается без какого-либо из этих трех способов присвоения высоты. У меня было такое, когда мне viewForHeaderзвонили, и заголовки появлялись нормально, пока однажды, без каких-либо изменений с моей стороны, этого не произошло . Именно тогда я начал экспериментировать, viewForHeaderчтобы определить минимальные требования для вызова. И теперь я знаю. И теперь вы тоже.
Мэтт
2
@texas Нет, я не занимаюсь xamarin. Добавление еще одного уровня косвенности поверх фреймворков Cocoa просто взорвало бы мою голову. :)
matt
20

Предоставление estimatedSectionHeaderHeightи sectionHeaderHeightценности устранили мою проблему. например, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension

Шарух Мастан
источник
Моя проблема началась после обновления до Swift 3.1. Это решение исправило это.
zevij
@pbuchheit Apple Docs сообщает, что он доступен с iOS 7.0+, пожалуйста, посмотрите здесь, developer.apple.com/documentation/uikit/uitableview/ ...
Шарух Мастан
@Sharukh Mastan Похоже, вы правы. По какой-то причине я получал предупреждение, когда пытался использовать это свойство, но оно исчезло после выполнения чистой сборки.
pbuchheit
7

Отказавшись от ответа rmaddy, я пытался скрыть представление заголовка и возвращал 0,0f для «tableView: heightForHeaderInSection» и вид с нулевой высотой tableView:viewForHeaderInSection.

После перехода с return 1.0fна return 0.0fin действительно был вызван tableView:heightForHeaderInSectionметод делегата tableView:viewForHeaderInSection.

Оказывается, желаемый эффект работает без использования tableView: heightForHeaderInSection; но это может быть полезно для других, у которых возникла проблема с вызовом метода делегата tableView: heightForHeaderInSection.

rrrrrraul
источник
5

Вы должны реализовать tableView:heightForHeaderInSection:и установить высоту заголовка> 0.

Этот метод делегата сопровождает viewForHeaderInSection:метод.

Надеюсь, это поможет.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
         return 40;
}
Chiara
источник
Вы проверили, действительно ли ваш ответ работает? Becaus e, если вы внимательно прочитали, тогда сказано, что изначально вызывается viewForHeaderInSection. Он не вызывается только при перезагрузке стола!
Карлис
5

Стоит вкратце отметить, что если ваша реализация tableView:heightForHeaderInSection:вернет UITableViewAutomaticDimension, то tableView:viewForHeaderInSection:называться не будет.

UITableViewAutomaticDimensionпредполагает, что UITableViewHeaderFooterViewбудет использоваться стандарт , который заполняется методом делегата tableView:titleForHeaderInSection:.

Из комментариев в UITableView.h:

Возврат этого значения из tableView:heightForHeaderInSection:или tableView:heightForFooterInSection:приводит к высоте, которая соответствует значению, возвращенному из tableView:titleForHeaderInSection:или, tableView:titleForFooterInSection:если заголовок не равен нулю.

Benjohn
источник
1
если вы установите estimatedSectionHeaderHeightкакое-то значение, tableView:viewForHeaderInSectionбудет вызываться (аналогично тому, как работают автоматические измерения для строк)
GreatWiz
Интересно, спасибо. Еще в версии 7.1 эта тонкость расчетной высоты была важна для ячеек , так же, как и для заголовков, но сейчас это не очень актуально!
Benjohn
3

У меня только что возникла проблема с заголовками, которые не отображаются для iOS 7.1 , но отлично работают с более поздними версиями, которые я тестировал, явно с 8.1 и 8.4.

Для того же самого кода 7.1 вообще не вызывал никаких методов делегата заголовка раздела, включая: tableView:heightForHeaderInSection:и tableView:viewForHeaderInSection:.

После экспериментов я обнаружил, что удаление этой строки из моих viewDidLoadсозданных заголовков снова появляется в 7.1 и не влияет на другие версии, которые я тестировал:

// _Removing_ this line _fixed_ headers on 7.1
self.tableView.estimatedSectionHeaderHeight = 80;

… Так что вроде бы там хоть какой-то конфликт для 7.1.

Benjohn
источник
3

У меня возникла такая же проблема, но поскольку я использовал автоматический расчет высоты из xCode 9 , я не могу указать явное значение высоты, как упомянуто выше. После некоторых экспериментов я получил решение , мы должны переопределить этот метод как,

-(CGFloat)tableView:(UITableView *)tableView 
         estimatedHeightForHeaderInSection:(NSInteger)section
{
      return 44.0f;
}

Хотя я проверил оба варианта

  1. Автоматический расчет высоты
  2. Автоматический расчет предполагаемой высоты

из раскадровки, как говорит яблоко, но все же я получил эту странную ошибку.

Обратите внимание : эта ошибка отображалась только в версии IOS-10, но не в версии IOS-11 . Может это ошибка xCode. Спасибо

Наджам
источник
0

Вот что я нашел ( Swift 4 ) (благодаря этому комментарию по другому вопросу)

Независимо от того, использовал ли я titleForHeaderInSection или viewForHeaderInSection - дело не в том, что они не вызывались при прокрутке tableview и загрузке новых ячеек, но любой выбор шрифта, который я сделал для textLabel headerView, появлялся только на том, что изначально было видно при загрузке , а не во время прокрутки таблицы.

Исправление было willDisplayHeaderView:

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    if let header = view as? UITableViewHeaderFooterView {
        header.textLabel?.font = UIFont(name: yourFont, size: 42)
    }
}
RanLearns
источник
0

В моем случае я создал представление заголовка, используя UITableviewCellи возвращая ячейку, viewForHeaderInSectionкак это

return cell

изменил это на

return cell.contentView 

Работал у меня.

user1547608
источник
0

В моем случае

viewForHeaderInSection

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

Антон Тропашко
источник
0

Причина, по которой viewForHeaderInSectionне вызывается, может быть по одной из двух причин:

Либо вы не настроили свой UITableViewDelegate, либо UITableViewDelegateнеправильно настроили .

Джем Йылмаз
источник
0

В моем случае это была причина, по которой я не реализовал:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
Наиль Шарипов
источник
-1

Иногда эту проблему может вызвать установка tableview.delegateили datasource = nilв методах viewWillAppear:или viewDidAppear:. Постарайтесь этого не делать ...

Houzyi
источник
-1

Я вырезал и вставил следующие два метода из проекта Swift 2 в свой проект Swift 3, которые никогда не вызывались, потому что в Swift 3 эти методы должны иметь «-» перед именем первого параметра.

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 44.0
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: B2BTrolleyHeaderFooterView.reuseIdentifier) as! B2BTrolleyHeaderFooterView        
    return headerView
}
koira
источник