2010-09-17 5 views
4

J'ai quelque chose de bizarre à utiliser UINib, bien que je soupçonne que le vrai problème peut être enterré ailleurs.Problème étrange utilisant UINib/pointeur allant AWOL

Mon application utilise une vue de table, le contenu pour les cellules a été préparé dans Interface Builder en raison de leur complexité. Pour les nouvelles cellules (par opposition aux nouvelles), le contenu de la plume est instancié à l'aide du UINib Class. Comme il n'y a qu'une seule plume utilisée pour toutes les cellules et pour réduire le temps de chargement du fichier à chaque fois, j'ai ajouté un UINib comme propriété cellNib à ma sous-classe viewcontroller que je charge une fois dans mon implémentation de viewDidLoad.

Maintenant, pour la partie étrange. Tout fonctionne correctement, la tableview est remplie avec ses données et toutes les cellules sont configurées avec le contenu de la plume comme elles devraient l'être. Mais dès que je fais défiler la tableview, l'application se bloque.
La callstack a donné ceci: - [NSCFNumber instantiateWithOwner: options:]: sélecteur non reconnu envoyé à l'instance Évidemment, le message pour instancier à nouveau le contenu de cellNib a été envoyé au mauvais objet. L'objet auquel le message est envoyé diffère de temps en temps, il y a donc quelque chose de aléatoire. Je ne comprends pas - pourquoi ça marche environ 10 fois en chargeant la tableview, mais plus quand on fait défiler la tableview?

Si je crée une nouvelle instance de UINib chaque temps (comme vu dans mon code ci-dessous), alors tout fonctionne très bien, le défilement inclus.

Où puis-je faire une erreur? Le pointeur de ma propriété UINib est-il actif? Si oui, pourquoi??

Voici le code que je utilise (je l'ai enlevé tout le chargement de données et d'autres choses pour le rendre plus facile à lire):

@interface NTDPadViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> { 

    NSManagedObjectContext *managedObjectContext; 
    NSMutableArray *ntdArray; 
    IBOutlet UITableView *ntdTableView; 
    UINib *cellNib; 

} 

@property(nonatomic,retain) NSManagedObjectContext *managedObjectContext; 
@property(nonatomic,retain) NSMutableArray *ntdArray; 
@property(nonatomic,retain) UITableView *ntdTableView; 
@property(nonatomic,retain) UINib *cellNib; 

@end 

La mise en œuvre:

@implementation NTDPadViewController 

@synthesize managedObjectContext; 
@synthesize ntdArray; 
@synthesize ntdTableView; 
@synthesize cellNib; 

-(void)viewDidLoad { 

    [super viewDidLoad]; 
    cellNib = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 

} 

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 
     [cell setBackgroundColor:[UIColor clearColor]]; 

     // These two should work equally well. But they don't... of course I'm using only one at a time ;) 
     // THIS WORKS: 
     UINib *test = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 
     NSArray *nibArray = [test instantiateWithOwner:self options:nil]; 

     // THIS DOESN'T WORK: 
     NSArray *nibArray = [cellNib instantiateWithOwner:self options:nil]; 

     [[cell contentView] addSubview:[nibArray objectAtIndex:0]]; 

    } 

    return cell; 
} 

Merci beaucoup !!

Répondre

7

Cette ligne attribue un autorelease d exemple à cellNib:

cellNib = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 

Cela signifie que la ligne suivante:

NSArray *nibArray = [cellNib instantiateWithOwner:self options:nil]; 

... cellNib est déjà désattribuées lorsque sa piscine autorelease associée a été drainée et l'utiliser entraînera un comportement indéfini.

Si vous souhaitez que cellNib reste, prenez-en possession, par exemple. en utilisant la propriété déclarée:

self.cellNib = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 
+0

vous avez absolument raison. Ça marche maintenant. Pourriez-vous expliquer pourquoi il y a une différence entre cellNib = et self.cellNib =? J'ai toujours pensé dans le contexte d'un objet se référant à une propriété par soi-même. était "optionnel" ... (stupide moi) – Toastor

+0

@Toastor: Ces deux variantes font des choses complètement différentes. 'self.cellNib = ...' est la "syntaxe de point" qui invoque le setter qui dans votre cas conserve. 'cellNib = ...' juste assigné directement à l'ivar, écrasant la valeur précédente du pointeur. Voir la section [propriétés déclarées] (http://developer.apple.com/bibliothèque/mac/# documentation/cacao/conceptuel/objectivec/Articles/ocProperties.html) dans les documents Apples pour plus de détails. –

+0

Super! Merci encore! – Toastor