Ответы:
Вы ищете это решение:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
который может отображать / скрывать / перезагружать любые статические ячейки с анимацией или без нее!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
Примечание всегда использовать только (reloadDataAnimated: YES / NO) (не вызывайте [self.tableView reloadData] напрямую)
Это не использует хакерское решение с установкой высоты 0 и позволяет вам анимировать изменения и скрывать целые разделы
IBOutletCollection
но я не вижу, как это повлияет на разницу. Я только вчера загрузил код, поэтому не думаю, что это старая версия.
Чтобы скрыть статические ячейки в UITable:
В вашем классе делегата контроллера UITableView:
Objective-C:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if(cell == self.cellYouWantToHide)
return 0; //set the hidden cell's height to 0
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Swift:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
Этот метод будет вызываться для каждой ячейки в UITable. После вызова ячейки, которую вы хотите скрыть, мы устанавливаем ее высоту равной 0. Мы идентифицируем целевую ячейку, создав для нее выход:
ClipToBounds
проблемы, вы также можете сделать ячейку скрытой. Мне это показалось бы чище. ;-)
Лучший способ, как описано в следующем блоге http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
Создайте представление статической таблицы как обычно в конструкторе интерфейса - со всеми потенциально скрытыми ячейками. Но есть одна вещь, которую вы должны сделать для каждой потенциальной ячейки, которую вы хотите скрыть - проверьте свойство «Обрезать подпредставления» ячейки, иначе содержимое ячейки не исчезнет, когда вы попытаетесь скрыть ее (уменьшив ее высоту - подробнее позже).
ТАК - у вас есть переключатель в ячейке, и предполагается, что переключатель скрывает и показывает некоторые статические ячейки. Подключите его к IBAction и там сделайте это:
[self.tableView beginUpdates]; [self.tableView endUpdates];
Это дает вам хорошую анимацию для появления и исчезновения клеток. Теперь реализуйте следующий метод делегата табличного представления:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need // Show or hide cell if (self.mySwitch.on) { return 44; // Show the cell - adjust the height as you need } else { return 0; // Hide the cell } } return 44; }
И это все. Нажмите переключатель, и ячейка скроется и снова появится с красивой плавной анимацией.
Мое решение идет в том же направлении, что и Гарет, хотя кое-что я делаю иначе.
Поехали:
1. Скройте ячейки
Нет возможности напрямую скрыть ячейки. UITableViewController
- это источник данных, который предоставляет статические ячейки, и в настоящее время нет способа сказать ему «не предоставлять ячейку x». Таким образом, мы должны предоставить собственный источник данных, который делегирует функции UITableViewController
объекту для получения статических ячеек.
Проще всего создать подкласс UITableViewController
и переопределить все методы, которые должны вести себя по-другому при скрытии ячеек .
В простейшем случае (таблица с одним разделом, все ячейки имеют одинаковую высоту) это будет выглядеть так:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Recalculate indexPath based on hidden cells
indexPath = [self offsetIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath
{
int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections
int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row
int offsetRow = indexPath.row + numberOfCellsHiddenAbove;
return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection];
}
Если в вашей таблице несколько разделов или ячейки имеют разную высоту, вам необходимо переопределить другие методы. Здесь применяется тот же принцип: вам нужно сместить indexPath, section и row перед делегированием super.
Также имейте в виду, что параметр indexPath для таких методов, как didSelectRowAtIndexPath:
будет отличаться для одной и той же ячейки в зависимости от состояния (т. Количества скрытых ячеек). Поэтому, вероятно, будет хорошей идеей всегда смещать любой параметр indexPath и работать с этими значениями.
2. Анимируйте изменение
Как уже сказал Гарет, вы получаете серьезные сбои, если вы анимируете изменения, используя reloadSections:withRowAnimation:
метод.
Я обнаружил, что если вы позвоните reloadData:
сразу после этого, анимация значительно улучшится (остались только незначительные глюки). После анимации таблица отображается правильно.
Итак, что я делаю, это:
- (void)changeState
{
// Change state so cells are hidden/unhidden
...
// Reload all sections
NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])];
[tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
numberOfRowsInSection:
вызывается только при первой загрузке таблицы. Когда я вызываю [self.tableView reloadData] - меня numberOfRowsInSection:
больше не вызывают. Только cellForRowAtIndexPath:
называется. Чего мне не хватает?
cellOneOutlet.hidden = true
теперь переопределите метод ниже, проверьте, какой статус ячейки скрыт, и верните высоту 0 для этих ячеек. Это один из многих способов скрыть любую ячейку в статическом tableView в swift.
override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat
{
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
if tableViewCell.hidden == true
{
return 0
}
else{
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
. Я предполагаю, что он заменен на let tableViewCell = tableView.cellForRow(at: indexPath as IndexPath)
.
UITableViewController
, у меня нет UITableView
методов делегатов. heightForRow
Нужны ли мне и другие методы, чтобы вызвать его?
Я придумал альтернативу, которая фактически скрывает разделы и не удаляет их. Я попробовал подход @ henning77, но продолжал сталкиваться с проблемами, когда менял количество разделов статического UITableView. Этот метод мне очень понравился, но я в первую очередь пытаюсь скрыть разделы, а не строки. Я удаляю некоторые строки на лету, но это намного сложнее, поэтому я попытался сгруппировать вещи в секции, которые мне нужно показать или скрыть. Вот пример того, как я скрываю разделы:
Сначала я объявляю свойство NSMutableArray
@property (nonatomic, strong) NSMutableArray *hiddenSections;
В viewDidLoad (или после того, как вы запросили свои данные) вы можете добавить разделы, которые вы хотите скрыть в массив.
- (void)viewDidLoad
{
hiddenSections = [NSMutableArray new];
if(some piece of data is empty){
// Add index of section that should be hidden
[self.hiddenSections addObject:[NSNumber numberWithInt:1]];
}
... add as many sections to the array as needed
[self.tableView reloadData];
}
Затем реализуйте следующие методы делегата TableView
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return nil;
}
return [super tableView:tableView titleForHeaderInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
return 0;
}
return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
[cell setHidden:YES];
}
}
Затем установите высоту верхнего и нижнего колонтитула на 1 для скрытых разделов, потому что вы не можете установить высоту на 0. Это приводит к дополнительному 2 пиксельному пространству, но мы можем компенсировать это, отрегулировав высоту следующего видимого заголовка.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = [super tableView:tableView heightForHeaderInSection:section];
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
height = 1; // Can't be zero
}
else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil
// Adjust height for previous hidden sections
CGFloat adjust = 0;
for(int i = (section - 1); i >= 0; i--){
if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){
adjust = adjust + 2;
}
else {
break;
}
}
if(adjust > 0)
{
if(height == -1){
height = self.tableView.sectionHeaderHeight;
}
height = height - adjust;
if(height < 1){
height = 1;
}
}
}
return height;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return 1;
}
return [super tableView:tableView heightForFooterInSection:section];
}
Затем, если у вас есть определенные строки, которые нужно скрыть, вы можете настроить numberOfRowsInSection и то, какие строки возвращаются в cellForRowAtIndexPath. В этом примере у меня есть раздел с тремя строками, любые три из которых могут быть пустыми и должны быть удалены.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = [super tableView:tableView numberOfRowsInSection:section];
if(self.organization != nil){
if(section == 5){ // Contact
if([self.organization objectForKey:@"Phone"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"Email"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"City"] == [NSNull null]){
rows--;
}
}
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
Используйте этот offsetIndexPath для вычисления indexPath для строк, из которых вы условно удаляете строки. Не требуется, если вы только скрываете разделы
- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath
{
int row = indexPath.row;
if(self.organization != nil){
if(indexPath.section == 5){
// Adjust row to return based on which rows before are hidden
if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){
row = row + 2;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){
row++;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
}
}
NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];
return offsetPath;
}
Есть много методов для переопределения, но что мне нравится в этом подходе, так это то, что его можно использовать повторно. Настройте массив hiddenSections, добавьте к нему, и он скроет правильные разделы. Скрыть ряды немного сложнее, но возможно. Мы не можем просто установить высоту строк, которые мы хотим скрыть, равной 0, если мы используем сгруппированный UITableView, потому что границы не будут отображаться правильно.
NSMutableSet
для hiddenSections
вместо. Это намного быстрее, поскольку вы в основном тестируете членство.
NSMutableSet
для использования for hiddenSections
, хотя я понимаю, что суть вашего ответа была более концептуальной, чем придирчивой, относительно того, какой тип структуры данных вы должны использовать.
Оказывается, вы можете скрывать и отображать ячейки в статическом UITableView - и с анимацией. И это не так уж и сложно.
Видео демонстрационного проекта
Суть:
Use tableView:heightForRowAtIndexPath:
для динамического определения высоты ячеек на основе некоторого состояния.tableView.beginUpdates();tableView.endUpdates()
tableView.cellForRowAtIndexPath:
заходите внутрь tableView:heightForRowAtIndexPath:
. Используйте кэшированные indexPaths, чтобы различать ячейки.Да, это определенно возможно, хотя сейчас я борюсь с той же проблемой. Мне удалось заставить клетки спрятаться, и все работает нормально, но в настоящее время я не могу аккуратно оживить их. Вот что я нашел:
Я скрываю строки в зависимости от состояния переключателя ВКЛ / ВЫКЛ в первой строке первого раздела. Если переключатель находится в положении ON, под ним в том же разделе находится 1 строка, в противном случае - 2 разные строки.
У меня есть селектор, вызываемый при переключении переключателя, и я устанавливаю переменную, чтобы указать, в каком состоянии я нахожусь. Затем я вызываю:
[[self tableView] reloadData];
Я переопределяю функцию tableView: willDisplayCell: forRowAtIndexPath: и, если ячейка должна быть скрыта, я делаю следующее:
[cell setHidden:YES];
Это скрывает ячейку и ее содержимое, но не удаляет занимаемое ею пространство.
Чтобы удалить пробел, переопределите tableView: heightForRowAtIndexPath: и верните 0 для строк, которые должны быть скрыты.
Вам также необходимо переопределить tableView: numberOfRowsInSection: и вернуть количество строк в этом разделе. Здесь нужно сделать что-то странное, чтобы, если ваш стол был сгруппированным, закругленные углы появлялись в правильных ячейках. В моей статической таблице есть полный набор ячеек для раздела, поэтому есть первая ячейка, содержащая параметр, затем 1 ячейка для параметров состояния ВКЛ и еще 2 ячейки для параметров состояния ВЫКЛ, всего 4 ячейки. Когда опция включена, я должен вернуть 4, это включает скрытую опцию, так что последняя отображаемая опция имеет закругленную рамку. Когда опция отключена, последние две опции не отображаются, поэтому я возвращаю 2. Это все кажется неуклюжим. Извините, если это не очень понятно, сложно описать. Просто, чтобы проиллюстрировать настройку, это конструкция раздела таблицы в IB:
Таким образом, когда опция включена, в таблице отображаются две строки:
Когда опция ВЫКЛЮЧЕНА, таблица содержит четыре строки:
Этот подход не кажется правильным по нескольким причинам, так же, как я дошел до моих экспериментов, поэтому, пожалуйста, дайте мне знать, если вы найдете лучший способ. До сих пор я наблюдал следующие проблемы:
Было бы неправильно сообщать таблице, что количество строк отличается от того, что предположительно содержится в базовых данных.
Кажется, я не могу оживить это изменение. Я пробовал использовать tableView: reloadSections: withRowAnimation: вместо reloadData, и результаты, похоже, не имеют смысла, я все еще пытаюсь заставить это работать. В настоящее время, похоже, происходит то, что tableView не обновляет правильные строки, поэтому одна остается скрытой, которая должна отображаться, а под первой строкой остается пустота. Я думаю, это может быть связано с первым пунктом о базовых данных.
Надеюсь, кто-нибудь сможет предложить альтернативные методы или, возможно, расширить с помощью анимации, но, возможно, это поможет вам начать. Приношу свои извинения за отсутствие гиперссылок на функции, я вставил их, но они были отклонены спам-фильтром, потому что я довольно новый пользователь.
[[self tableView] reloadData];
еще раз после того, как я спрятала камеры
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
в UITableViewController
подклассе для создания статических ячеек. Пути индексов индексируются статически, а не динамически ...
Согласно ответу Джастаса, но для Swift 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
tableView.reloadRows(at:, with:)
обновить ячейки, если вы измените высоту, когда строка уже видна.
Ладно, после некоторых попыток у меня есть необычный ответ. Я использую переменную isHidden или скрытый, чтобы проверить, должна ли эта ячейка быть скрытой.
создайте IBOutlet для вашего контроллера представления.
@IBOutlet weak var myCell: UITableViewCell!
Обновите myCell
в своей пользовательской функции, например, вы можете добавить ее в viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.myCell.isHidden = true
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
guard !cell.isHidden else {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
Это уменьшит вашу логику в методе делегата, и вам нужно будет сосредоточиться только на своих бизнес-требованиях.
Приведенные выше ответы, которые скрывают / отображают ячейки, изменяют rowHeight или беспорядок с ограничениями автоматического макета, не работали для меня из-за проблем с автоматическим макетом. Код стал невыносимым.
Для простой статической таблицы мне лучше всего было:
Вот пример из моего контроллера табличного представления:
@IBOutlet weak var titleCell: UITableViewCell!
@IBOutlet weak var nagCell: UITableViewCell!
@IBOutlet weak var categoryCell: UITableViewCell!
var cellsToShow: [UITableViewCell] = []
override func viewDidLoad() {
super.viewDidLoad()
determinCellsToShow()
}
func determinCellsToShow() {
if detail!.duration.type != nil {
cellsToShow = [titleCell, nagCell, categoryCell]
}
else {
cellsToShow = [titleCell, categoryCell]
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cellsToShow[indexPath.row]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsToShow.count
}
Для iOS 11 я обнаружил, что модифицированная версия лучше всего ответа Мохамеда Салеха с некоторыми улучшениями, основанными на документации Apple. Он прекрасно анимируется, избегает уродливых взломов или жестко запрограммированных значений и использует высоту строк, уже установленную в Interface Builder. .
Основная идея состоит в том, чтобы установить высоту строки равной 0 для любых скрытых строк. Тогда используйтеtableView.performBatchUpdates
для запуска анимации, которая работает стабильно.
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == indexPathOfHiddenCell {
if cellIsHidden {
return 0
}
}
// Calling super will use the height set in your storyboard, avoiding hardcoded values
return super.tableView(tableView, heightForRowAt: indexPath)
}
Вы хотите убедиться, cellIsHidden
и indexPathOfHiddenCell
правильно настроены на ваш случай использования. Для моего кода они являются свойствами моего контроллера табличного представления.
В любом методе управления видимостью (вероятно, с помощью кнопки или didSelectRow
) переключите состояние cellIsHidden внутри performBatchUpdates
блока:
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
Apple рекомендует performBatchUpdates
больше beginUpdates
иendUpdates
всегда, когда это возможно.
Я нашел решение для анимации скрытых ячеек в статической таблице.
// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
BlockExecutor * executor = [[BlockExecutor alloc] init];
executor.block = block;
return executor;
}
@end
Требуется только один дополнительный словарь:
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
И посмотрите на реализацию MyTableViewController. Нам нужны два метода для преобразования indexPath между видимым и невидимым индексами ...
- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row <= indexPath.row + rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}
- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row < indexPath.row - rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}
Одно действие IBAction при изменении значения UISwitch:
- (IBAction)birthdaySwitchChanged:(id)sender
{
NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
if (self.birthdaySwitch.on)
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
else
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Некоторые методы UITableViewDataSource и UITableViewDelegate:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
if (indexPath.section == section)
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
numberOfRows -= (executor.block()?0:1);
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initializing dictionary
self.hidableCellsDict = [NSMutableDictionary dictionary];
[self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}
- (void)viewDidUnload
{
[self setBirthdaySwitch:nil];
[super viewDidUnload];
}
@end
Ответь в кратчайшие сроки :
Добавьте следующий метод в свой TableViewController:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
если tableView пытается нарисовать ячейку, которую вы хотите скрыть, он не будет отображаться, потому что его высота будет установлена на 0pt благодаря описанному выше методу, все остальное остается неизменным.
Обратите внимание, что indexPathOfCellYouWantToHide
можно изменить в любой момент :)
В> Swift 2.2 я собрал здесь несколько ответов.
Сделайте выход из раскадровки для ссылки на свой staticCell.
@IBOutlet weak var updateStaticCell: UITableViewCell!
override func viewDidLoad() {
...
updateStaticCell.hidden = true
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 0
} else {
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
Я хочу скрыть свою первую ячейку, поэтому установил высоту 0, как описано выше.
Свифт 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var height = super.tableView(tableView, heightForRowAt: indexPath)
if (indexPath.row == HIDDENROW) {
height = 0.0
}
return height
}
В самом простом сценарии, когда вы скрываете ячейки в самом низу представления таблицы, вы можете настроить tableView contentInset после того, как скроете ячейку:
- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}
Это новый способ сделать это с помощью https://github.com/k06a/ABStaticTableViewController.
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
Решение от k06a ( https://github.com/k06a/ABStaticTableViewController ) лучше, потому что оно скрывает весь раздел, включая верхние и нижние колонтитулы ячеек, где это решение ( https://github.com/peterpaulis/StaticDataTableViewController ) скрывает все, кроме нижнего колонтитула.
РЕДАКТИРОВАТЬ
Я только что нашел решение, если вы хотите скрыть нижний колонтитул StaticDataTableViewController
. Вот что вам нужно скопировать в файл StaticTableViewController.m:
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
} else {
return [super tableView:tableView titleForFooterInSection:section];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
CGFloat height = [super tableView:tableView heightForFooterInSection:section];
if (self.originalTable == nil) {
return height;
}
if (!self.hideSectionsWithHiddenRows) {
return height;
}
OriginalSection * os = self.originalTable.sections[section];
if ([os numberOfVissibleRows] == 0) {
//return 0;
return CGFLOAT_MIN;
} else {
return height;
}
//return 0;
return CGFLOAT_MIN;
}
Конечно можно. Во-первых, вернитесь к вашему tableView количество ячеек, которое вы хотите показать, затем вызовите super
для достижения определенной ячейки из вашей раскадровки и верните ее для tableView:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.mode.numberOfCells()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
return cell
}
Если у ваших ячеек другая высота, верните и ее:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
В дополнение к решению @Saleh Masum:
Если вы получаете ошибки автоматического макета , вы можете просто удалить ограничения изtableViewCell.contentView
Свифт 3:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)
if tableViewCell.isHidden == true
{
tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
return 0
}
else{
return super.tableView(tableView, heightForRowAt: indexPath)
}
}
Это решение зависит от потока вашего приложения . Если вы хотите показать / скрыть ячейку в том же экземпляре контроллера представления, это может быть не лучшим выбором, поскольку он снимает ограничения .
У меня появился лучший способ динамически скрывать статические ячейки и даже разделы без каких-либо взломов.
Установка высоты строки на 0 может скрыть строку, но это не сработает, если вы хотите скрыть весь раздел, который будет содержать некоторые пробелы, даже если вы скрываете все строки.
Мой подход заключается в создании массива секций статических ячеек. Тогда содержимое табличного представления будет управляться массивом разделов.
Вот пример кода:
var tableSections = [[UITableViewCell]]()
private func configTableSections() {
// seciton A
tableSections.append([self.cell1InSectionA, self.cell2InSectionA])
// section B
if shouldShowSectionB {
tableSections.append([self.cell1InSectionB, self.cell2InSectionB])
}
// section C
if shouldShowCell1InSectionC {
tableSections.append([self.cell1InSectionC, self.cell2InSectionC, self.cell3InSectionC])
} else {
tableSections.append([self.cell2InSectionC, self.cell3InSectionC])
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return tableSections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableSections[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return tableSections[indexPath.section][indexPath.row]
}
Таким образом, вы можете собрать весь свой код конфигурации без необходимости написания неприятного кода для вычисления количества строк и разделов. И конечно нет0
высот.
Этот код также очень легко поддерживать. Например, если вы хотите добавить / удалить больше ячеек или разделов.
Аналогично, вы можете создать массив заголовков разделов и массив заголовков нижнего колонтитула раздела, чтобы динамически конфигурировать заголовки разделов.