Réponses:
Vous recherchez cette solution:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
qui peut afficher / masquer / recharger n'importe quelle (s) cellule (s) statique (s) avec ou sans animation!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
Remarque à toujours utiliser uniquement (reloadDataAnimated: YES / NO) (ne pas appeler [self.tableView reloadData] directement)
Cela n'utilise pas la solution hacky avec le réglage de la hauteur à 0 et vous permet d'animer le changement et de masquer des sections entières
IBOutletCollection
mais je ne vois pas en quoi cela ferait une différence. Je n'ai téléchargé le code qu'hier, donc je ne pense pas que ce soit une ancienne version.
Pour masquer les cellules statiques dans UITable:
Dans votre classe de délégué de contrôleur UITableView:
Objectif 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];
}
Rapide:
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)
}
Cette méthode sera appelée pour chaque cellule de l'UITable. Une fois qu'il l'appelle pour la cellule que vous souhaitez masquer, nous définissons sa hauteur sur 0. Nous identifions la cellule cible en lui créant une sortie:
ClipToBounds
problème, vous pouvez également définir la cellule sur masquée. Cela me paraîtrait plus propre. ;-)
Le meilleur moyen est celui décrit dans le blog suivant http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
Concevez votre vue de tableau statique comme d'habitude dans le générateur d'interface - avec toutes les cellules potentiellement masquées. Mais il y a une chose que vous devez faire pour chaque cellule potentielle que vous souhaitez masquer - cochez la propriété "Clip sous-vues" de la cellule, sinon le contenu de la cellule ne disparaît pas lorsque vous essayez de la masquer (en réduisant sa hauteur - plus tard).
SO - vous avez un commutateur dans une cellule et le commutateur est censé se cacher et afficher des cellules statiques. Connectez-le à une IBAction et faites-le:
[self.tableView beginUpdates]; [self.tableView endUpdates];
Cela vous donne de belles animations pour les cellules qui apparaissent et disparaissent. Maintenant, implémentez la méthode de délégation de vue table suivante:
- (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; }
Et c'est tout. Actionnez le commutateur et la cellule se cache et réapparaît avec une belle animation fluide.
Ma solution va dans le même sens que Gareth, bien que je fasse certaines choses différemment.
Voici:
1. Cachez les cellules
Il n'y a aucun moyen de masquer directement les cellules. UITableViewController
est la source de données qui fournit les cellules statiques, et actuellement il n'y a aucun moyen de lui dire "ne pas fournir la cellule x". Nous devons donc fournir notre propre source de données, qui délègue au UITableViewController
afin d'obtenir les cellules statiques.
Le plus simple est de sous UITableViewController
-classer et de remplacer toutes les méthodes qui doivent se comporter différemment lors du masquage de cellules .
Dans le cas le plus simple (table à section unique, toutes les cellules ont la même hauteur), cela ressemblerait à ceci:
- (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 votre tableau comporte plusieurs sections ou si les cellules ont des hauteurs différentes, vous devez remplacer d'autres méthodes. Le même principe s'applique ici: vous devez décaler indexPath, section et row avant de déléguer à super.
Gardez également à l'esprit que le paramètre indexPath pour des méthodes telles que didSelectRowAtIndexPath:
sera différent pour la même cellule, en fonction de l'état (c'est-à-dire le nombre de cellules masquées). C'est donc probablement une bonne idée de toujours compenser tout paramètre indexPath et de travailler avec ces valeurs.
2. Animer le changement
Comme Gareth l'a déjà déclaré, vous obtenez des problèmes majeurs si vous animez les modifications à l'aide de la reloadSections:withRowAnimation:
méthode.
J'ai découvert que si vous appelez reloadData:
immédiatement après, l'animation est beaucoup améliorée (il ne reste que de petits problèmes). Le tableau s'affiche correctement après l'animation.
Donc ce que je fais, c'est:
- (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:
sont appelées uniquement lorsque la table se charge pour la première fois. Quand j'appelle [self.tableView reloadData] - numberOfRowsInSection:
n'est plus jamais appelé. Seul cellForRowAtIndexPath:
est appelé. Qu'est-ce que je rate?
cellOneOutlet.hidden = true
remplacez maintenant la méthode ci-dessous, vérifiez quel état de cellule est masqué et renvoyez la hauteur 0 pour ces cellules. C'est l'une des nombreuses façons de masquer n'importe quelle cellule dans tableView statique dans 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)
. Je suppose qu'il est remplacé par let tableViewCell = tableView.cellForRow(at: indexPath as IndexPath)
.
UITableViewController
, je n'ai aucune UITableView
méthode de délégation. Pour pouvoir l'appeler heightForRow
, ai-je également besoin d'autres méthodes?
J'ai trouvé une alternative qui cache en fait les sections et ne les supprime pas. J'ai essayé l'approche de @ henning77, mais j'ai continué à rencontrer des problèmes lorsque j'ai changé le nombre de sections de l'UITableView statique. Cette méthode a très bien fonctionné pour moi, mais j'essaie principalement de masquer des sections au lieu de lignes. Je supprime certaines lignes à la volée avec succès, mais c'est beaucoup plus compliqué, j'ai donc essayé de regrouper les choses en sections que je dois afficher ou masquer. Voici un exemple de la façon dont je cache des sections:
Je déclare d'abord une propriété NSMutableArray
@property (nonatomic, strong) NSMutableArray *hiddenSections;
Dans le viewDidLoad (ou après avoir interrogé vos données), vous pouvez ajouter des sections que vous souhaitez masquer au tableau.
- (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];
}
Ensuite, implémentez les méthodes de délégué TableView suivantes
- (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];
}
}
Ensuite, définissez la hauteur de l'en-tête et du pied de page sur 1 pour les sections masquées car vous ne pouvez pas définir la hauteur sur 0. Cela entraîne un espace supplémentaire de 2 pixels, mais nous pouvons le compenser en ajustant la hauteur de l'en-tête visible suivant.
-(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];
}
Ensuite, si vous avez des lignes spécifiques à masquer, vous pouvez ajuster le numberOfRowsInSection et les lignes renvoyées dans cellForRowAtIndexPath. Dans cet exemple, j'ai une section qui comporte trois lignes où trois d'entre elles peuvent être vides et doivent être supprimées.
- (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]];
}
Utilisez ce offsetIndexPath pour calculer l'indexPath pour les lignes où vous supprimez conditionnellement des lignes. Pas nécessaire si vous ne masquez que des sections
- (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;
}
Il existe de nombreuses méthodes à remplacer, mais ce que j'aime dans cette approche, c'est qu'elle est réutilisable. Configurez le tableau hiddenSections, ajoutez-y et il masquera les sections correctes. Cacher les rangées c'est un peu plus délicat, mais possible. Nous ne pouvons pas simplement définir la hauteur des lignes que nous voulons masquer à 0 si nous utilisons un UITableView groupé car les bordures ne seront pas dessinées correctement.
NSMutableSet
pour à la hiddenSections
place. C'est beaucoup plus rapide car vous testez principalement l'adhésion.
NSMutableSet
for hiddenSections
, même si je comprends que le point de votre réponse était plus conceptuel que pointilleux quant au type de structure de données à utiliser.
Il s'avère que vous pouvez masquer et afficher des cellules dans un UITableView statique - et avec une animation. Et ce n'est pas si difficile à accomplir.
Vidéo du projet de démonstration
L'essentiel:
Use tableView:heightForRowAtIndexPath:
pour spécifier les hauteurs de cellule de manière dynamique en fonction d'un état.tableView.beginUpdates();tableView.endUpdates()
tableView.cellForRowAtIndexPath:
intérieurtableView:heightForRowAtIndexPath:
. Utilisez les indexPaths mis en cache pour différencier les cellules.Oui, c'est certainement possible, même si je suis aux prises avec le même problème pour le moment. J'ai réussi à masquer les cellules et tout fonctionne bien, mais je ne peux pas actuellement faire en sorte que la chose s'anime proprement. Voici ce que j'ai trouvé:
Je cache des lignes en fonction de l'état d'un interrupteur ON / OFF dans la première ligne de la première section. Si le commutateur est sur ON, il y a 1 ligne en dessous dans la même section, sinon il y a 2 lignes différentes.
J'ai un sélecteur appelé lorsque le commutateur est basculé, et je règle une variable pour indiquer dans quel état je me trouve. Ensuite, j'appelle:
[[self tableView] reloadData];
Je remplace la tableView: willDisplayCell: forRowAtIndexPath: function et si la cellule est censée être masquée, je fais ceci:
[cell setHidden:YES];
Cela masque la cellule et son contenu, mais ne supprime pas l'espace qu'elle occupe.
Pour supprimer l'espace, remplacez la tableView: heightForRowAtIndexPath: function et renvoyez 0 pour les lignes qui doivent être masquées.
Vous devez également remplacer tableView: numberOfRowsInSection: et renvoyer le nombre de lignes dans cette section. Vous devez faire quelque chose d'étrange ici pour que si votre tableau est un style groupé, les coins arrondis apparaissent sur les cellules correctes. Dans mon tableau statique, il y a l'ensemble complet de cellules pour la section, donc il y a la première cellule contenant l'option, puis 1 cellule pour les options d'état ON et 2 autres cellules pour les options d'état OFF, un total de 4 cellules. Lorsque l'option est activée, je dois retourner 4, cela inclut l'option masquée afin que la dernière option affichée ait une boîte arrondie. Lorsque l'option est désactivée, les deux dernières options ne sont pas affichées, donc je retourne 2. Tout cela semble maladroit. Désolé si ce n'est pas très clair, c'est difficile à décrire. Juste pour illustrer la configuration, voici la construction de la section de table dans IB:
Ainsi, lorsque l'option est activée, le tableau indique deux lignes qui sont:
Lorsque l'option est désactivée, le tableau indique quatre lignes qui sont:
Cette approche ne semble pas correcte pour plusieurs raisons, c'est tout ce que j'ai obtenu avec mon expérimentation jusqu'à présent, alors faites-moi savoir si vous trouvez un meilleur moyen. Les problèmes que j'ai observés jusqu'à présent sont:
Il est faux de dire à la table que le nombre de lignes est différent de ce qui est vraisemblablement contenu dans les données sous-jacentes.
Je n'arrive pas à animer le changement. J'ai essayé d'utiliser tableView: reloadSections: withRowAnimation: au lieu de reloadData et les résultats ne semblent pas avoir de sens, j'essaie toujours de faire fonctionner cela. Actuellement, ce qui semble se produire, c'est que tableView ne met pas à jour les lignes correctes, donc l'une reste cachée qui doit être affichée et un vide est laissé sous la première ligne. Je pense que cela pourrait être lié au premier point concernant les données sous-jacentes.
J'espère que quelqu'un pourra suggérer des méthodes alternatives ou peut-être comment étendre avec l'animation, mais peut-être que cela vous aidera à démarrer. Mes excuses pour le manque d'hyperliens vers les fonctions, je les ai mis mais ils ont été rejetés par le filtre anti-spam car je suis un utilisateur assez récent.
[[self tableView] reloadData];
une fois de plus après avoir caché les cellules
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
sous- UITableViewController
classe pour créer des cellules statiques. Les chemins d'index sont indexés statiquement - pas dynamiques ...
Selon la réponse de Justas, mais pour 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:)
mettre à jour les cellules si vous modifiez la hauteur alors que la ligne est déjà visible.
D'accord, après quelques essais, j'ai une réponse non commune. J'utilise la variable "isHidden" ou "hidden" pour vérifier si cette cellule doit être masquée.
créez un IBOutlet dans votre contrôleur de vue.
@IBOutlet weak var myCell: UITableViewCell!
Mettez à jour le myCell
dans votre fonction personnalisée, par exemple, vous pouvez l'ajouter dans 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)
}
Cela réduira votre logique dans la méthode de délégué et vous n'aurez qu'à vous concentrer sur vos besoins commerciaux.
Les réponses ci-dessus qui masquent / affichent les cellules, modifient rowHeight ou gâchent les contraintes de mise en page automatique ne fonctionnaient pas pour moi en raison de problèmes de mise en page automatique. Le code est devenu intolérable.
Pour une simple table statique, ce qui fonctionnait le mieux pour moi était de:
Voici un exemple de mon contrôleur de vue de table:
@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
}
Pour iOS 11, j'ai trouvé qu'une version modifiée de la réponse de Mohamed Saleh fonctionnait le mieux, avec quelques améliorations basées sur la documentation d'Apple. Il s'anime bien, évite les hacks ou les valeurs codées en dur et utilise des hauteurs de ligne déjà définies dans Interface Builder .
Le concept de base est de définir la hauteur de ligne sur 0 pour toutes les lignes masquées. Utilisez ensuite tableView.performBatchUpdates
pour déclencher une animation qui fonctionne de manière cohérente.
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)
}
Vous voudrez vous assurer cellIsHidden
et indexPathOfHiddenCell
sont définis de manière appropriée à votre cas d'utilisation. Pour mon code, ce sont des propriétés sur mon contrôleur de vue table.
Quelle que soit la méthode qui contrôle la visibilité (probablement une action de bouton ou didSelectRow
), basculez l'état cellIsHidden, à l'intérieur d'un performBatchUpdates
bloc:
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
Apple recommande performBatchUpdates
plus beginUpdates
/endUpdates
chaque fois que possible.
J'ai trouvé une solution pour animer les cellules de masquage dans un tableau statique.
// 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
Un seul dictionnaire supplémentaire nécessaire:
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
Et regardez l'implémentation de MyTableViewController. Nous avons besoin de deux méthodes pour convertir indexPath entre les index visibles et 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];
}
Une IBAction sur la modification de la valeur 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];
}
Certaines méthodes UITableViewDataSource et 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
Répondez rapidement :
Ajoutez la méthode suivante dans votre TableViewController:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
si le tableView essaie de dessiner la cellule que vous souhaitez masquer, il ne l'affichera pas car sa hauteur sera fixée à 0pt grâce à la méthode ci-dessus, tout le reste reste inchangé.
Veuillez noter que cela indexPathOfCellYouWantToHide
peut être modifié à tout moment :)
Dans> Swift 2.2, j'ai combiné quelques réponses ici.
Créez une sortie à partir du storyboard pour créer un lien vers votre 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)
}
}
Je veux masquer ma première cellule, donc je règle la hauteur sur 0 comme décrit ci-dessus.
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
}
Pour le scénario le plus simple lorsque vous masquez des cellules tout en bas de la vue tableau, vous pouvez ajuster le contentInset de tableView après avoir masqué la cellule:
- (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);
}
C'est une nouvelle façon de faire cela en utilisant https://github.com/k06a/ABStaticTableViewController
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
La solution de k06a ( https://github.com/k06a/ABStaticTableViewController ) est meilleure car elle cache toute la section, y compris les en-têtes et les pieds de page des cellules, où cette solution ( https://github.com/peterpaulis/StaticDataTableViewController ) cache tout sauf le pied de page.
ÉDITER
Je viens de trouver une solution si vous souhaitez masquer le pied de page StaticDataTableViewController
. Voici ce que vous devez copier dans le fichier 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;
}
Vous pouvez sûrement. Tout d'abord, revenez à votre tableau Afficher le nombre de cellules que vous souhaitez afficher, puis appelez super
pour obtenir une certaine cellule de votre storyboard et renvoyez-le pour 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 vos cellules ont une hauteur différente, renvoyez-la également:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
En plus de la solution @Saleh Masum:
Si vous obtenez des erreurs de mise en page automatique , vous pouvez simplement supprimer les contraintes dutableViewCell.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)
}
}
Cette solution dépend du flux de votre application . Si vous souhaitez afficher / masquer la cellule dans la même instance de contrôleur de vue, ce n'est peut-être pas le meilleur choix, car cela supprime les contraintes .
J'ai eu un meilleur moyen de masquer les cellules statiques et même les sections de manière dynamique sans aucun piratage.
La définition de la hauteur de ligne à 0 peut masquer une ligne, mais cela ne fonctionne pas si vous souhaitez masquer une section entière qui contiendra des espaces même si vous masquez toutes les lignes.
Mon approche consiste à créer un tableau de sections de cellules statiques. Ensuite, le contenu de la vue de table sera piloté par le tableau de sections.
Voici un exemple de code:
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 cette façon, vous pouvez rassembler tout votre code de configuration sans avoir à écrire le mauvais code pour calculer le nombre de lignes et de sections. Et bien sûr, non0
hauteurs.
Ce code est également très facile à maintenir. Par exemple, si vous souhaitez ajouter / supprimer d'autres cellules ou sections.
De même, vous pouvez créer un tableau de titre d'en-tête de section et un tableau de titre de pied de page pour configurer dynamiquement vos titres de section.