2010-07-09 4 views
2

J'ai une méthode pour générer un objet Deck (sous-classe NSObject avec une propriété NSMutableArray) et il remplit le tableau avec des objets Card (UIView sous-classe avec un certain nombre et une propriété NSString). Quand je demande un Deck, je vérifie s'il existe déjà (je pense) et si c'est le cas, relâchez-le avant d'en avoir un nouveau.Instruments dit que j'ai une fuite de mémoire, mais je ne le vois pas

Le code de mon viewcontroller ...

#import "FlashTestViewController.h" 

@implementation FlashTestViewController 

- (IBAction)generateDeck { 

    if (aDeck != nil) { 
     [aDeck release]; 
    } 

    aDeck = [[Deck alloc] initDeckWithOperator:@"+"]; 
} 


- (IBAction)generateCard { 

    if (aCard != nil) { 
     [aCard fadeAway]; 
    } 

    aCard = [aDeck newCardFromDeck]; 
    [self.view addSubview:aCard]; 
} 

- (void)fadeAway { 
    [aCard removeFromSuperview]; 
    [aCard release]; 
    } 

    @end 

La classe de plate-forme est la suivante ...

#import <Foundation/Foundation.h> 
#import "Card.h" 

@class Deck; 

@interface Deck : NSObject { 

    NSMutableArray* cards; 
} 

@property(nonatomic, retain) NSMutableArray* cards; 

- (id)initDeckWithOperator: (NSString*)mathOper; 
- (id)newCardFromDeck; 

@end 

- (id)initDeckWithOperator: (NSString*)mathOper { 

    if (cards != nil) { 
     [cards release]; 
    } 
    cards = [[NSMutableArray alloc] init]; 
    for (int i=0; i<11; i++) { 
     for (int j=0; j<11; j++) { 
      int xPos = (random() % 220) + 10; 
      int yPos = (random() % 360) + 10; 
      Card* aCard = [[Card alloc] initWithFrame:CGRectMake(xPos, yPos, 60, 80)]; 
      aCard.upperOperand = i; 
      aCard.lowerOperand = j; 
      aCard.theOperator = mathOper; 
      aCard.theResult = i + j; 

      UITextView* upperTextView = [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 50, 20)]; 
     NSString* upperOper = [[NSString alloc] initWithFormat:@"  %d", i]; 
     upperTextView.text = upperOper; 
     [aCard addSubview:upperTextView]; 
     [upperTextView release]; 
     [upperOper release]; 

     UITextView* middleTextView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 50, 20)]; 
     NSString* middleOper = [[NSString alloc] initWithFormat:@"%@ %d", mathOper, j]; 
     middleTextView.text = middleOper; 
     [aCard addSubview:middleTextView]; 
     [middleTextView release]; 
     [middleOper release]; 

     UITextView* lowerTextView = [[UITextView alloc] initWithFrame:CGRectMake(5, 55, 50, 20)]; 
     NSString* lowerOper = [[NSString alloc] initWithFormat:@"  %d", j+i]; 
      lowerTextView.text = lowerOper; 
      [aCard addSubview:lowerTextView]; 
      [lowerTextView release]; 
      [lowerOper release]; 

      [cards addObject: aCard]; 
      [aCard release]; 
     } 
    } 
    return self; 
} 

- (id)newCardFromDeck { 
    int index = random() % [cards count]; 
    Card* selectedCard = [[cards objectAtIndex:index] retain]; 
    [cards removeObjectAtIndex:index]; 
    return selectedCard; 
} 

@end 

Je fais la même chose quand je demande une nouvelle carte de la méthode newCardFromDeck et cela fonctionne. Aucune suggestion?

Merci!

+0

Vous ne voyez pas la fuite? Il y a des morceaux partout sur le sol! – Dima

+0

Libérez-vous des 'cartes'? – conorgriffin

Répondre

2

Ajouter ce code à votre fichier Deck.m:

- (void)dealloc 
{ 
    [cards release]; 
    [super dealloc]; 
} 
+0

J'ai sous-classé NSObject (pour la première fois) et j'ai l'habitude d'obtenir automatiquement le dealloc, ce qui me rappelle de sortir des trucs là-bas. Je reçois la fuite de mémoire chaque fois que je génère une nouvelle Deck. Est-ce que la version que je ferais au début se débarrasserait du vieux tableau de cartes? Et dans la méthode du contrôleur, je vérifie une instance existante de Deck et s'il y en a une, relâchez-la là. Au moins, ce que je pense que je fais. – Steve

+0

Lorsque vous créez une nouvelle Deck, vous obtenez automatiquement un nouveau tableau de cartes. Tout le reste que je peux voir se passe (y compris en libérant le Deck dans votre contrôleur de vue) semble bon, le déroutement de dealloc dans votre objet Deck est appelé lorsque vous relâchez l'objet de pont de votre contrôleur de vue. N'oubliez pas le super, juste pour vous assurer que tout ce que vous sous-classer a également une chance de libérer. –

2

En regardant cette ligne de code:

cards = [[NSMutableArray alloc] init]; 

Avez-vous relâchiez cards dans votre méthode dealloc? Il semble que cela pourrait être une fuite de mémoire.

+0

Je suppose que je ne comprends pas exactement quand dealloc pour une classe particulière est appelée. Je ne l'appelle nulle part explicitement - en fait je n'avais même pas de méthode dealloc car j'ai sous-classé NSObject et je ne l'ai pas ajouté. – Steve

+0

Vous devriez en faire un. 'dealloc' est appelé quand votre objet est libéré. Vous (devriez) jamais l'appeler directement, mais le framework Cocoa le fera. – mipadi

+0

Il est plus précis de dire que ça s'appelle quand l'objet est libéré et qu'il n'y a plus d'objet pour le conserver. – Chuck

0

aDeck dans generateDeck est aussi être une fuite si vous ne relâchez pas dans la dealloc de la vue.

0

En newCardFromDeck:

Card* selectedCard = [[cards objectAtIndex:index] retain]; 

ressemble à vous conservez la carte et le retourner quelque part. Où cette valeur de retour finit-elle? S'il finit dans une autre variable avec une propriété 'retain', il peut être conservé une seconde fois (lors de l'affectation à la variable).

Questions connexes