Récupérer la taille des custom cells
Bonjour,
je suis en train de coder une collectionView avec des custom cells.
J'ai besoin de connaà®tre la taille de ces custom cells, que j'indique dans la méthode delegate de collection view.
Comme je ne veux pas coder en dur la taille de ma custom cell, j'ai procédé comme ceci.
#import "MyCell.h"
static CGSize _size ;
@interface MyCell ()
@property (weak, nonatomic) IBOutlet UIButton *button;
@end
@implementation MyCell
+ (CGSize)size
{
if (_size.height == 0
||
_size.width == 0)
{
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class])
owner:[[self alloc] init]
options:nil] ;
}
return _size ;
}
- (void)awakeFromNib
{
_size = self.frame.size ;
}
@end
Je voulais avoir votre avis.
Est-ce une bonne façon de faire ?
Comme ça, je ne verrais qu'une autre solution : charger tous mes nibs au lancement de l'app.
En fait, le problème auquel j'ai été confronté, c'est que la collection view appelle la méthode delegate pour connaà®tre la taille de la cell, le xib n'a pas encore été réveillé. Donc, le code suivant plante :
#import "MyCell.h"
static CGSize _size ;
@interface MyCell ()
@property (weak, nonatomic) IBOutlet UIButton *button;
@end
@implementation MyCell
+ (CGSize)size
{
// if (_size.height == 0
// ||
// _size.width == 0)
// {
// [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class])
// owner:[[self alloc] init]
// options:nil] ;
// }
return _size ;
}
- (void)awakeFromNib
{
_size = self.frame.size ;
}
@end
D'où ma solution.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
L'inconvénient de ta solution est qu'elle réaffecte size à chaque fois qu'une cellule est instanciée, que ce soit par ton loadNibNamed:owner:options: ou par la CollectionView.
L'autre inconvénient est que charger un XIB juste pour récupérer la taille, c'est un peu lourd. En plus tu instancies une cell avec alloc+init pour en faire le file's Owner... d'une autre cell que tu vas instancier avec le XIB, donc 2 cells (une par alloc/init, l'autre par XIB) juste pour ça !
Mais en même temps, le fait de charger la taille par le XIB, ça te garantis que tu as la bonne taille, celle issue du XIB, et pas une taille mise dans une constante que tu oublierais de changer dans ton code si un jour tu changes ton XIB... donc c'est quand même utile...
Moi ce que je fais dans ces cas-là , c'est que je prend le meilleur des 2 mondes : chargement du XIB en DEBUG pour extraire la taille du XIB, et utilisation d'une constante en RELEASE.
Après, c'est une façon de faire comme une autre, mais c'est une pratique que j'aime bien et que j'utilise souvent.
T'es sûr de cette ligne ?
ça paraà®t être en contradiction avec
Merci de ta réponse !
Voici une version améliorée !
- Utilisation de NSValue au lieu d'utiliser directement CGSize : mais pourquoi donc ?!
- Surcharge de awakeFromNib pour rien
- Non thread-safe (pas de dispatch_once, utilisation d'un objet en variable globale " ze truc à éviter " et non d'une constante et d'un type non-objet
- Pas de valeur const pour optimiser la version release
Je voulais faire un test sur les attributs de classe, à base de
+ (void)setColor:(UIColor *)Color
qui interagirait avec un objet en variable globale.
J'ai l'impression que ça bugue....
Je testerai ça demain.
Merci de vos retours
Oulà faut réviser d'urgence tes cours, en particulier les risques avec le multithreading et les accès concurrents aux variables globales (risques de crash assurés, et journées de debug impossibles en perspectives jusqu'à te rendre compte que des bugs aléatoires viennent de là !). Avec les variables globales, dont l'accès concurrent n'est pas protégées, tu peux préparer tes bons de réduction pour les tubes d'aspirine.
On peut déclarer une constante en globale (car elle ne sera que lue), mais une variable globale (qui peut donc être écrite et lue de manière potentiellement concurrente, et générer des race conditions), c'est le mal absolu, tu risques d'avoir des bugs bien prise de tête et aléatoires !
En même temps je ne vois de toute façons pas le rapport avec ta problématique, en quoi cela t'ai t'aiderait dans ton cas ? En quoi l'utilisation d'une static affectée une seule fois de façon threadsafe avec un dispatch_once ne solutionne pas ton problème ? Ou même mieux l'utilisation d'une constante comme dans mon code ?
Du coup j'ai fait comme ça :
Dans mon cas, j'ai dû remplace
par le nom en dur, car la méthode est appelée depuis une classe fille et c'est le nom de la classe fille qui est retourné... et qu'il n'y a pas de xib avec ce nom !!
En fait, c'est toute la ligne
qui faisait râler xcode, à cause de IBOutlets je pense. Si le owner est nil, il n'arrive pas à connecter les outlets, je pense.
Du coup, j'ai remis le crado [[self alloc] init]
Apparemment, quand les outlets sont connectés au file's owner, ça bugue. C'est le cas des view controllers.
ça marche si les outlets sont connectés à un objet. C'est les cas des custom cells.
cf. http://stackoverflow.com/a/5479906/1670830 et en particulier le commentaire liké 7 fois
En fait, j'ai un xib qui est lié à un VC.
Mais, j'ai besoin, connaà®tre de "l'extraire à vide" pour gérer une méthode +(CGSize)size (cf. début du post --> en fait, j'ai voulu adapté ces méthodes à un xib qui n'est pas une custom cell).