web-dev-qa-db-fra.com

Valeur incorrecte de UITableView: rowHeight sur iOS8

Le code que j'avais utilisé pour créer un rectangle (au moins jusqu'à iOS7) était

CGRect rect = [cTableView frame];
rect.Origin.y += [cTableView rowHeight];
searchOverlayView = [[BecomeFirstResponderControl alloc] initWithFrame:rect];

Sur iOS7, cTableView (une instance de UITableView) a renvoyé 44. Le test dans iOS8 avec un iPhone 5s renvoie -1

Pourquoi cela arrive-t-il? Quel est le code correct à utiliser pour que mon application soit rétrocompatible avec iOS7? 

19
cateof

Apple a modifié la hauteur de ligne par défaut dans iOS8 en UITableViewAutomaticDimension, déclarée en tant que -1. Cela signifie que votre vue sous forme de tableau est configurée pour le calcul automatique de la hauteur des cellules.

Vous devrez soit implémenter autoLayout (recommandé), soit implémenter la nouvelle méthode de délégué: heightForRowAtIndexPath. Voici une excellente question à propos de la présentation automatique: Utilisation de la disposition automatique dans UITableView pour des dispositions de cellules dynamiques et des hauteurs de ligne variables

On dirait que vous avez quand même codé dur (l’ancien par défaut) de toute façon, donc vous pouvez simplement le faire (non recommandé).

19
Rog

Cela m'a fait lutter pendant des heures. J'ai fini par coder la valeur à 44:

self.tableView.rowHeight = 44;
15
Js Lim

L'implémentation de heightForRowAtIndexPath présente un inconvénient que je préfère ne pas encourir lorsque toutes les lignes d'un tableau ont la même hauteur et ne changent jamais à l'exécution (il est appelé une fois pour chaque ligne, à chaque affichage du tableau). 

Dans cette situation, je continue à définir "Row Height" dans XIB et à utiliser le code convivial iOS 8 suivant lorsque j'ai besoin de rowHeight (il fonctionne également sur iOS 7 et versions ultérieures).

NSInteger aRowHeight = self.tableView.rowHeight;
if (-1 == aRowHeight)
{
    aRowHeight = 44;
}

Cela vous permet de continuer à éditer librement Row Height dans XIB et fonctionnera même si Apple corrige ce bogue/cette fonctionnalité ultérieurement et si un ensemble XIB Row Height = 44 cesse de revenir à -1.

2
Swany

Si vous modifiez accidentellement la hauteur de ligne dans IB de 44 à quelque chose d'autre (40 par exemple), le calcul automatique de la taille de la cellule échoue. Tu me dois 3 heures, Apple.

1
Paul Bruneau

Une autre considération est que si vous calculez la hauteur en fonction des dimensions de vue existantes, la méthode heightForRowAtIndexPath peut être appelée avant viewDidLayoutSubviews.

Dans ce cas, remplacez viewDidLayoutSubviews et recalculez la valeur frame.size.height pour toutes les cellules visibles. 

0
user3259235

Ma solution à ce problème:

@interface MCDummyTableView () <UITableViewDataSource, UITableViewDelegate>
@end

@implementation MCDummyTableView

    - (instancetype) initWithFrame:(CGRect)frame style:(UITableViewStyle)style {
        frame = (CGRect){ 0, 0, 100, 100 };

        self = [super initWithFrame:frame style:style];
        if(!self) return self;

        self.dataSource = self;
        self.delegate = self;

        [self registerClass:[UITableViewCell class] forCellReuseIdentifier:@"CELL"];

        return self;
    }

    - (NSInteger) numberOfSections {
        return 1;
    }

    - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return 1;
    }

    - (UITableViewCell*) cellForRowAtIndexPath:(NSIndexPath*)indexPath {
        /*
            UITableView doesn't want to generate cells until it's in the view hiearchy, this fixes that.
            However, if this breaks (or you don't like it) you can always add your UITableView to a UIWindow, then destroy it
            (that is likely the safer solution).
        */

        return [self.dataSource tableView:self cellForRowAtIndexPath:indexPath];
    }

    - (UITableViewCell*) tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
        return [self dequeueReusableCellWithIdentifier:@"CELL"];
    }

    - (CGFloat) defaultRowHeight {
        return [self cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]].frame.size.height;
    }

@end

Je n'aime vraiment pas les choses en dur. J'utilise cette classe pour mettre en cache la hauteur de cellule par défaut au début de l'application.

0
mattsven