Как скрыть UITableViewSections в Swift?

У меня есть статическое сгруппированное представление таблицы, которое имеет 5 разделов (все разделы имеют заголовки, без нижних колонтитулов). Я создал все это с помощью раскадровки. Теперь, как я могу скрыть первый/верхний UITableViewSection (включая заголовок). Я попытался сделать выход в UITableViewSection, но он говорит мне, что он недопустим (необъявленный тип):

@IBOutlet var section: UITableViewSection!

Я сделал это так, потому что планировал:

section.hidden = true

Не может ли это быть сделано так?

Мои делегаты и источники данных настроены на 100% правильно.

Ответ 1

Вы можете использовать метод делегата:

override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
  if(section == 0)
    return 0.0
}

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

func numberOfRowsInSection(section: Int) -> Int {
  if (section == 0) {
    return 0
  }
  else {
  // return the number of rows you want
  }
}

EDIT (адресация Tim комментарий)

Чтобы получить синтаксис вправо:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if (section == 0) {
        return 0.0
    }
    return UITableViewAutomaticDimension
}

Или более аккуратный switch-case синтаксис:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    switch section {
    case 0:
        return 0.0
    default:
        return UITableViewAutomaticDimension
    }
}

Я тестировал оба, и они работают нормально.

Ответ 2

0.0 не работал у меня. Я должен был сделать это, чтобы заставить его работать.

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

    switch section {
    case 0:
        return 0.01
    default:
        return UITableViewAutomaticDimension
    }
}

Ответ 3

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

Ответ выше был очень полезен в моем сценарии. Тем не менее, для тех, кто не всегда знает, какой раздел нужно будет скрывать здесь, является решением для вас, которое распространяется на вышеупомянутое.

В моем сценарии у меня есть до 12 записей в массиве, который я хочу показать до 12 разделов (среди других разделов в grouped tableView). Если на дисплее отображено менее 12 записей, я хочу скрыть ненужные разделы, указав им 0 высоту и 0 строк. Я также хотел скрыть заголовок.

Чтобы сделать это, я сделал следующее:

  • Настройте свой TableView в соответствии с отличным ответом @sasquatch. выше.
  • В номереOfRowsInSection (раздел: Int) и tableView (_ tableView: UITableView, heightForHeaderInSection: Int), проверьте, должны ли строки/высота быть 0.

В моем случае я использовал разделы 1-12 для своих динамических данных, поэтому я использовал следующий код:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    //For section 0 and 13, just 1 row is ok
    if section == 0 || section == 13 {
        return 1
    }

    //For sections 1 - 12, determine if we have data to populate it, or if we should hide it
    if section <= dynamicDataToDisplay.count {
        return 2
    }

    //If it section 1 - 12, but we don't have a corresponding data entry in dynamicDataToDisplay, then just return 0 rows
    return 0

}

Код для функции heightForHeader аналогичен логике:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

    switch section {

    case 0:
        return 45.0
    case 13:
        return UITableViewAutomaticDimension
    default:
        if dynamicDataToDisplay.count >= section {
           return 25.0
        } else {
            return 0.0
        }

    } //end switch

}

Даже после настройки этих функций я обнаружил, что все еще получаю заголовки для разделов, которые я хотел скрыть. Думаю, я думал, что viewForHeaderInSection не будет вызываться, если numberOfRows равно 0, а heightOfHeader тоже 0, но он все еще вызывался.

Добавление следующего помогло гарантировать, что заголовок не был создан без необходимости:

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

    //set up header for dynamic data sections
    if 1 ... 12 ~= section  {

        if tableView.numberOfRows(inSection: section) == 0 {
            return nil
        }
        //Continue with the header set up for valid sections with rows to display data

        ......
    }
}

Это решение может помочь любому, кто все еще создает заголовок, несмотря на то, что его высота и строки установлены в 0.

Ответ 4

Для группы UITableView со статическими ячейками работает только это решение:

self.tableView.sectionHeaderHeight = 0;
self.tableView.sectionFooterHeight = 0;

override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    let count = self.tableView(tableView, numberOfRowsInSection: section)
    if count == 0 {
        return CGFloat(Double.leastNormalMagnitude)
    }
    return 44.0
}

Ответ 5

Я также хотел бы, чтобы вы просто @IBOutlet в раздел и @IBOutlet его, но, к сожалению, это не так, так что...

Основываясь на различных предложениях здесь, я установил следующее, которое не требует вмешательства в явные значения размера и сохраняет то, что вы уже могли установить на раскадровке /XIB. Это просто делает заголовок ноль и количество строк 0 для любого раздела, который вы хотите скрыть (что приводит к размеру 0.0).

Очевидно, вы можете настроить sectionShouldBeHidden для работы так, как вам нужно; сокрытие # 1 и # 3 - просто произвольные примеры.

Swift v5

private func sectionShouldBeHidden(_ section: Int) -> Bool {
    switch section {
    case 1, 3: return true
    default: return false
    }
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if sectionShouldBeHidden(section) {
        return nil // Show nothing for the header of hidden sections
    } else {
        return super.tableView(tableView, titleForHeaderInSection: section) // Use the default header for other sections
    }
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if sectionShouldBeHidden(section) {
        return 0 // Don't show any rows for hidden sections
    } else {
        return super.tableView(tableView, numberOfRowsInSection: section) // Use the default number of rows for other sections
    }
}

Обновление: К сожалению, вышеприведенного достаточно только в том случае, если стиль табличного представления - Plain. Когда это Grouped, там также добавляется дополнительное пространство между каждым разделом, о котором тоже нужно позаботиться. Это дополнительное пространство является нижним колонтитулом раздела, поэтому может быть обработано так:

override public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    if sectionShouldBeHidden(section) {
        return CGFloat.leastNormalMagnitude // Use the smallest possible value for hidden sections
    } else {
        return super.tableView(tableView, heightForFooterInSection: section) // Use the default footer height for other sections
    }
}