2010-11-09 3 views
2

J'utilisais l'outil "Allocations" d'Apple et j'ai remarqué que lorsque je passais d'une vue à l'autre, l'allocation augmentait toujours. En enquêtant, j'ai découvert que toute la mémoire provient d'objets qui sont des sous-vues de UIView de mon UIViewController.UIViewController est correctement désalloué mais son UIView n'est pas?

J'ai vérifié et mon UIViewController est libéré, mais apparemment le UIView n'est pas? Je ne retiens pas le UIView du contrôleur UIView. Quelqu'un a des idées?

Voici le code que j'ai écrit pour passer d'une vue à l'autre.

UISubViewController *viewController = [UIViewControllerFactory createViewController:viewControllerID];  // Creates and returns a UIViewController by ID 

[currentViewController viewWillDisappear:YES]; 
[currentViewController.view removeFromSuperview]; 
[currentViewController viewDidDisappear:YES]; 

[viewController viewWillAppear:YES]; 
[self.view insertSubview:viewController.view atIndex:0]; 
[viewController viewDidAppear:YES]; 

self.currentViewController = viewController; 
[viewController release]; 

Edit:
Ok, parce qu'il craignait que je juste en utilisant la vue d'un ViewController puis en relâchant le ViewController, j'ai essayé une expérience où j'ai fait une nouvelle classe qui est propriétaire du fichier dans le NIB, mais hérite de NSObject.

le code ressemble maintenant à ceci:

MyView *myView = [[MyView alloc] initWithNibName:@"myView"]; 

[currentView viewWillDisappear:YES]; 
[currentView.view removeFromSuperview]; 
[currentView viewDidDisappear:YES]; 

[myView viewWillAppear:YES]; 
[self.view insertSubview:myView.view atIndex:0]; 
[myView viewDidAppear:YES]; 

self.currentView = myView; 
[myView release]; 

de initialiseur de MyView ressemble:

@interface MyView : NSObject { 
    IBOutlet UIView *view; 
    NSArray *nibTopLevelObjects; 
} 

@property (nonatomic, retain) UIView *view; 

- (id)initWithNibName:(NSString *)nibName; 

@end 


@implementation MyView 

@synthesize view; 

- (id)initWithNibName:(NSString *)nibName { 
    if (self = [super init]) { 

     nibTopLevelObjects = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil]; 
     [nibTopLevelObjects retain]; 
    } 
    return self; 
} 

- (void)dealloc { 
    [view release]; 
    [nibTopLevelObjects release]; 

    view = nil; 
    nibTopLevelObjects = nil; 

    [super dealloc]; 
} 

@end 

Je vois encore la fuite de mémoire de la vue à chaque fois que j'échange et de nouvelles vues.

De nouvelles idées?

+0

Qu'est-ce que UIViewControllerFactory, et comment crée-t-il les vues? A partir de fichiers nib? – GendoIkari

+0

Oui, UIViewControllerFactory mappe simplement viewControllerID avec la chaîne correcte pour initWithNibName, puis renvoie le viewController. – PyongHopscotch

Répondre

0

Votre usine renvoie un viewController mais vous ne faites qu'ajouter une vue sans appuyer sur un nouveau contrôleur. Pourquoi ne pas simplement créer une vue dans ce cas?

Ce que vous faites remplace continuellement le fichier self.currentViewController ivar sans le relâcher. Vous pouvez libérer la vue appartenant à ce contrôleur de vue, mais c'est tout.

est-currentViewController défini comme

@property (nonatomic, retain) UISubViewController* currentViewController; 

peut-être? Si tel est le cas, il existe une conservation qui ne correspond pas à une version - vous ne libérez jamais self.currentViewController avant de l'écraser. Si vous n'utilisez pas self., il ne sera pas conservé même si la propriété a été définie.

+1

En fait, lorsque vous utilisez self. vous accédez à la propriété et non à l'ivar.La version synthétisée d'un '@property (retain) ...' libèrera l'ancien ivar avant de conserver le nouveau à chaque fois qu'il est défini en utilisant le soi. notation. –

+0

Adam, vous avez raison de dire que j'ai défini currentViewController, mais comme vous pouvez le voir dans mon extrait, j'appelle self.currentViewController qui libère correctement l'ancien ViewController avant d'assigner le nouveau. – PyongHopscotch

+0

Vous et Dean avez posé des questions sur mon ajout de la vue. Existe-t-il un meilleur moyen d'afficher la vue d'un ViewController? – PyongHopscotch

0

Vous supprimez correctement l'ancienne vue et en ajoutez une nouvelle. Cela signifie que quelque part dans votre SubViewController vous retenez par erreur la vue ou que vous testez dans le simulateur au lieu du périphérique. Pouvez-vous poster votre code pour un SubViewController pour voir ce qui se passe là-bas?

Et obtenez-vous les mêmes résultats lorsque vous testez sur un périphérique réel?


PS Adam Eberbach soulève un bon point - pourquoi ne vous dérange pas la création d'un contrôleur de vue juste pour voler est vue, puis relâchez-le?

+0

Je vais répondre à la question d'Adam ici comme je l'ai posté accidentellement ci-dessous avant que j'aie fini. Le ViewController ne disparaît pas, il est conservé via l'appel à self.currentViewController. J'ai encapsulé toute ma logique pour la vue dans son ViewController. J'ai donc un moyen standard de répondre à viewDidLoad, viewWillAppear, didReceiveMemoryWarning etc. – PyongHopscotch

+0

Je cours ceci dans le simulateur. Ne devrais-je pas être? Je vois le même comportement quand je cours sur l'appareil. – PyongHopscotch

Questions connexes