Respuestas:
Estás buscando esta solución:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
¡que puede mostrar / ocultar / recargar cualquier celda estática con o sin animación!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
Nota para usar siempre solo (reloadDataAnimated: YES / NO) (no llame [self.tableView reloadData] directamente)
Esto no utiliza la solución hacky con la configuración de altura a 0 y le permite animar el cambio y ocultar secciones enteras
IBOutletCollection
pero no veo cómo eso marcaría la diferencia. Solo descargué el código ayer, así que no creo que sea una versión antigua.
Para ocultar celdas estáticas en UITable:
En su clase delegada del controlador UITableView:
C objetivo:
- (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];
}
Rápido:
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)
}
Se llamará a este método para cada celda en la UITable. Una vez que lo llama para la celda que desea ocultar, establecemos su altura en 0. Identificamos la celda objetivo creando una salida para ella:
ClipToBounds
problema, también puede configurar la celda como oculta. Esto me parecería más limpio. ;-)
La mejor manera es como se describe en el siguiente blog http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
Diseñe su vista de tabla estática como normal en el generador de interfaces, completa con todas las celdas potencialmente ocultas. Pero hay una cosa que debe hacer por cada celda potencial que desea ocultar: verifique la propiedad "Subvistas de clip" de la celda, de lo contrario el contenido de la celda no desaparecerá cuando intente ocultarla (reduciendo su altura - más tarde).
SO: tiene un interruptor en una celda y se supone que el interruptor oculta y muestra algunas celdas estáticas. Conéctelo a un IBAction y allí haga esto:
[self.tableView beginUpdates]; [self.tableView endUpdates];
Eso te da animaciones agradables para las celdas que aparecen y desaparecen. Ahora implemente el siguiente método de delegado de vista de tabla:
- (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; }
Y eso es. Mueva el interruptor y la celda se esconde y vuelve a aparecer con una animación agradable y suave.
Mi solución va en una dirección similar a la de Gareth, aunque hago algunas cosas de manera diferente.
Aquí va:
1. Ocultar las celdas
No hay forma de ocultar directamente las celdas. UITableViewController
es la fuente de datos que proporciona las celdas estáticas, y actualmente no hay forma de decirle "no proporcione la celda x". Entonces tenemos que proporcionar nuestra propia fuente de datos, que delega enUITableViewController
para obtener las celdas estáticas.
Lo más fácil es subclasificar UITableViewController
y anular todos los métodos que deben comportarse de manera diferente al ocultar celdas .
En el caso más simple (tabla de sección única, todas las celdas tienen la misma altura), esto sería así:
- (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];
}
Si su tabla tiene varias secciones, o las celdas tienen diferentes alturas, debe anular más métodos. Aquí se aplica el mismo principio: debe compensar indexPath, section y row antes de delegar a super.
También tenga en cuenta que el parámetro indexPath para métodos como didSelectRowAtIndexPath:
será diferente para la misma celda, dependiendo del estado (es decir, el número de celdas ocultas). Por lo tanto, probablemente sea una buena idea compensar siempre cualquier parámetro indexPath y trabajar con estos valores.
2. Animar el cambio
Como ya dijo Gareth, obtienes fallas importantes si animas los cambios usando reloadSections:withRowAnimation:
método.
Descubrí que si llamas reloadData:
inmediatamente después, la animación mejora mucho (solo quedan pequeños fallos). La tabla se muestra correctamente después de la animación.
Entonces, lo que estoy haciendo es:
- (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:
solo se llama cuando la tabla se carga por primera vez. Cuando llamo a [self.tableView reloadData], numberOfRowsInSection:
nunca se vuelve a llamar. Solo cellForRowAtIndexPath:
se llama. ¿Qué me estoy perdiendo?
cellOneOutlet.hidden = true
ahora anule el método a continuación, verifique qué estado de celda está oculto y devuelva la altura 0 para esas celdas. Esta es una de las muchas formas en que puede ocultar cualquier celda en tableView estático de forma rápida.
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)
. Supongo que se reemplaza por let tableViewCell = tableView.cellForRow(at: indexPath as IndexPath)
.
UITableViewController
, no tengo ningún UITableView
método de delegado. Para que llame heightForRow
, ¿necesito también otros métodos?
Se me ocurrió una alternativa que en realidad oculta secciones y no las elimina. Intenté el enfoque de @ henning77, pero seguí teniendo problemas cuando cambié el número de secciones del UITableView estático. Este método me ha funcionado muy bien, pero principalmente estoy tratando de ocultar secciones en lugar de filas. Estoy eliminando algunas filas sobre la marcha con éxito, pero es mucho más complicado, por lo que he tratado de agrupar las cosas en secciones que necesito mostrar u ocultar. Aquí hay un ejemplo de cómo estoy ocultando secciones:
Primero declaro una propiedad NSMutableArray
@property (nonatomic, strong) NSMutableArray *hiddenSections;
En viewDidLoad (o después de haber consultado sus datos) puede agregar secciones que desea ocultar a la matriz.
- (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];
}
Luego implemente los siguientes métodos de delegado de 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];
}
}
Luego configure la altura del encabezado y pie de página en 1 para las secciones ocultas porque no puede establecer la altura en 0. Esto provoca un espacio adicional de 2 píxeles, pero podemos compensarlo ajustando la altura del siguiente encabezado visible.
-(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];
}
Luego, si tiene filas específicas para ocultar, puede ajustar numberOfRowsInSection y qué filas se devuelven en cellForRowAtIndexPath. En este ejemplo, aquí tengo una sección que tiene tres filas donde tres pueden estar vacías y deben eliminarse.
- (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]];
}
Use este offsetIndexPath para calcular el indexPath para las filas donde está eliminando condicionalmente las filas. No es necesario si solo está ocultando secciones
- (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;
}
Hay muchos métodos para anular, pero lo que me gusta de este enfoque es que es reutilizable. Configure la matriz hiddenSections, agréguela y ocultará las secciones correctas. Ocultando las filas es un poco más complicado, pero posible. No podemos simplemente establecer el alto de las filas que queremos ocultar a 0 si estamos usando un UITableView agrupado porque los bordes no se dibujarán correctamente.
NSMutableSet
para en su hiddenSections
lugar. Es mucho más rápido ya que en su mayoría está probando la membresía.
NSMutableSet
for hiddenSections
, aunque entiendo que el punto de su respuesta fue más conceptual que selectivo sobre qué tipo de estructura de datos debe usar.
Resulta que puede ocultar y mostrar celdas en un UITableView estático, y con animación. Y no es tan difícil de lograr.
Video de demostración del proyecto
La esencia:
Use tableView:heightForRowAtIndexPath:
para especificar las alturas de las celdas dinámicamente en función de algún estado.tableView.beginUpdates();tableView.endUpdates()
tableView.cellForRowAtIndexPath:
dentro tableView:heightForRowAtIndexPath:
. Use indexPaths en caché para diferenciar las celdas.Sí, definitivamente es posible, aunque estoy luchando con el mismo problema en este momento. Me las arreglé para ocultar las celdas y todo funciona bien, pero actualmente no puedo hacer que la cosa se anime claramente. Esto es lo que he encontrado:
Estoy ocultando filas en función del estado de un interruptor de ENCENDIDO / APAGADO en la primera fila de la primera sección. Si el interruptor está ENCENDIDO, hay 1 fila debajo de él en la misma sección; de lo contrario, hay 2 filas diferentes.
Tengo un selector llamado cuando se cambia el interruptor, y configuro una variable para indicar en qué estado estoy. Luego llamo:
[[self tableView] reloadData];
Anulo la función tableView: willDisplayCell: forRowAtIndexPath: y si se supone que la celda está oculta, hago esto:
[cell setHidden:YES];
Eso oculta la celda y su contenido, pero no elimina el espacio que ocupa.
Para eliminar el espacio, anule la tabla view: heightForRowAtIndexPath: y devuelva 0 para las filas que deberían estar ocultas.
También debe anular tableView: numberOfRowsInSection: y devolver el número de filas en esa sección. Debe hacer algo extraño aquí para que si su tabla es un estilo agrupado, las esquinas redondeadas se produzcan en las celdas correctas. En mi tabla estática hay un conjunto completo de celdas para la sección, por lo que está la primera celda que contiene la opción, luego 1 celda para las opciones de estado ON y 2 celdas más para las opciones de estado OFF, un total de 4 celdas. Cuando la opción está activada, tengo que devolver 4, esto incluye la opción oculta para que la última opción mostrada tenga un cuadro redondeado. Cuando la opción está desactivada, las dos últimas opciones no se muestran, así que devuelvo 2. Todo esto se siente torpe. Lo siento si esto no está muy claro, es difícil de describir. Solo para ilustrar la configuración, esta es la construcción de la sección de tabla en IB:
Entonces, cuando la opción está activada, la tabla informa dos filas que son:
Cuando la opción está DESACTIVADA, la tabla informa cuatro filas que son:
Este enfoque no se siente correcto por varias razones, es tan lejos como he llegado hasta ahora con mi experimentación, así que avíseme si encuentra una mejor manera. Los problemas que he observado hasta ahora son:
Se siente mal decirle a la tabla que el número de filas es diferente de lo que presumiblemente está contenido en los datos subyacentes.
Parece que no puedo animar el cambio. Intenté usar tableView: reloadSections: withRowAnimation: en lugar de reloadData y los resultados no parecen tener sentido, todavía estoy tratando de que esto funcione. Actualmente, lo que parece suceder es que tableView no actualiza las filas correctas, por lo que permanece oculto y se debe mostrar un vacío debajo de la primera fila. Creo que esto podría estar relacionado con el primer punto sobre los datos subyacentes.
Esperemos que alguien pueda sugerir métodos alternativos o tal vez cómo ampliar con la animación, pero tal vez esto lo ayude a comenzar. Pido disculpas por la falta de hipervínculos a las funciones, las puse pero el filtro de spam las rechazó porque soy un usuario bastante nuevo.
[[self tableView] reloadData];
una vez más después de ocultar las celdas
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
a la UITableViewController
subclase para crear celdas estáticas. Las rutas de índice son estáticas indexadas, no dinámicas ...
Según la respuesta de Justas, pero para 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:)
para actualizar las celdas si cambia la altura mientras la fila ya está visible.
Bien, después de intentarlo, tengo una respuesta no común. Estoy usando la variable "isHidden" u "hidden" para verificar si esta celda debe estar oculta.
cree un IBOutlet para su controlador de vista.
@IBOutlet weak var myCell: UITableViewCell!
Actualice el myCell
en su función personalizada, por ejemplo, puede agregarlo en 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)
}
Esto reducirá su lógica en el método de delegado, y solo necesita concentrarse en los requisitos de su negocio.
Las respuestas anteriores que ocultan / muestran celdas, cambian rowHeight o se meten con restricciones de diseño automático no me funcionaron debido a problemas de diseño automático. El código se volvió intolerable.
Para una tabla estática simple, lo que mejor funcionó para mí fue:
Aquí hay un ejemplo de mi controlador de vista de tabla:
@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
}
Para iOS 11, descubrí que una versión modificada de la respuesta de Mohamed Saleh funcionó mejor, con algunas mejoras basadas en la documentación de Apple. Anima muy bien, evita cualquier truco feo o valores codificados, y utiliza alturas de fila ya establecidas en Interface Builder .
El concepto básico es establecer el alto de fila en 0 para cualquier fila oculta. Luego, use tableView.performBatchUpdates
para activar una animación que funcione de manera consistente.
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)
}
Querrás asegurarte cellIsHidden
y indexPathOfHiddenCell
estar configurado adecuadamente para tu caso de uso. Para mi código, son propiedades en mi controlador de vista de tabla.
En cualquier método que controle la visibilidad (probablemente una acción de botón o didSelectRow
), alterna el estado cellIsHidden, dentro de un performBatchUpdates
bloque:
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
Apple recomienda performBatchUpdates
sobre beginUpdates
/endUpdates
siempre que sea posible.
Encontré una solución para animar las celdas ocultas en la tabla estática.
// 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
Solo se necesita un diccionario adicional:
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
Y observe la implementación de MyTableViewController. Necesitamos dos métodos para convertir indexPath entre índices visibles e invisibles ...
- (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];
}
Un cambio de valor de IBAction en 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];
}
Algunos métodos UITableViewDataSource y 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
Responda rápidamente :
Agregue el siguiente método en su TableViewController:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
si tableView intenta dibujar la celda que desea ocultar, no la mostrará porque su altura se establecerá en 0pt gracias al método anterior, todo lo demás permanece inalterado.
Tenga en cuenta que indexPathOfCellYouWantToHide
se puede cambiar en cualquier momento :)
En> Swift 2.2, he combinado algunas respuestas aquí.
Haga una salida del guión gráfico para vincular a su 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)
}
}
Quiero ocultar mi primera celda, así que configuré la altura en 0 como se describió anteriormente.
Swift 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
}
Para el escenario más fácil cuando oculta celdas en la parte inferior de la vista de tabla, puede ajustar el contenido de TableView después de ocultar la celda:
- (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);
}
Esta es una nueva forma de hacer esto usando https://github.com/k06a/ABStaticTableViewController
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
La solución de k06a ( https://github.com/k06a/ABStaticTableViewController ) es mejor porque oculta toda la sección, incluidos los encabezados y pies de página de las celdas, donde esta solución ( https://github.com/peterpaulis/StaticDataTableViewController ) oculta todo excepto el pie de página.
EDITAR
Acabo de encontrar una solución si quieres ocultar el pie de página StaticDataTableViewController
. Esto es lo que necesita copiar en el archivo 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;
}
Seguramente puedes. Primero, regrese al número de celdas tableView que desea mostrar, luego llame super
para lograr cierta celda de su guión gráfico y devuélvala para 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
}
Si sus celdas tienen una altura diferente, devuélvala también:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
Además de la solución @Saleh Masum:
Si obtiene errores de diseño automático , simplemente puede eliminar las restricciones deltableViewCell.contentView
Swift 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)
}
}
Esta solución depende del flujo de su aplicación . Si desea mostrar / ocultar la celda en la misma instancia del controlador de vista, esta puede no ser la mejor opción, ya que elimina las restricciones .
Obtuve una mejor manera de ocultar celdas estáticas e incluso secciones dinámicamente sin ningún truco.
Establecer el alto de fila en 0 puede ocultar una fila, pero eso no funciona si desea ocultar una sección completa que contendrá algunos espacios incluso si oculta todas las filas.
Mi enfoque es construir una matriz de secciones de celdas estáticas. Luego, el contenido de la vista de tabla será controlado por la matriz de secciones.
Aquí hay un código de muestra:
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]
}
De esta manera, puede armar todo su código de configuración sin tener que escribir el código desagradable para calcular el número de filas y secciones. Y por supuesto no0
alturas.
Este código también es muy fácil de mantener. Por ejemplo, si desea agregar / eliminar más celdas o secciones.
Del mismo modo, puede crear una matriz de título de encabezado de sección y una matriz de título de pie de página de sección para configurar sus títulos de sección dinámicamente.