2011-01-30 3 views
0

Supposons que j'ai deux classes. Dans le premier, je déclare ceci dans Class1.hiphone - essayer de comprendre @property

@interface Class1 : UIViewController { 

    NSString *myString; 
    id myObject; 

} 

Sur la deuxième classe je vais au-delà que je déclare comme

@interface Class2 : UIViewController { 

    NSString *myString; 
    id myObject; 

} 

@property (nonatomic, retain) NSString *myString; 
@property (nonatomic, retain) id myObject; 

puis je @synthesize myString, myObject sur Classe2. Puis, sur mon programme principal, je crée deux objets: un basé sur Class1 et un autre basé sur Class2.

Quel effet l'@property de classe2 aura-t-il? Est-ce que toutes les valeurs attribuées aux deux valeurs sur Class2 seront toujours conservées? Si oui, dois-je les "libérer"? Comment?

Merci.

Répondre

3

S'il vous plaît lire Declared Properties section of The Objective-C programming language pour une explication complète sur les propriétés;)

En Classe2:

Dans ce cas, vous définissez l'attribut retain sur votre propriété, il est supposé être conservé dans l'implémentation. Ceci est fait automatiquement lorsque vous synthétisez une propriété. Cela signifie que vous devez avoir

- (void) dealloc{ 
    [myString release]; 
    [myObject release]; 
    [super dealloc]; 
} 

et tout devrait bien

Dans Class1, vous n'avez pas des propriétés si myString et myObject ne sont pas visibles de l'extérieur. Mais cela ne signifie pas que vous ne devriez pas les libérer. Cela dépend de la façon dont vous les initialisez et/ou si vous leur envoyez des messages. Par ailleurs, si vous définissez assign sur une propriété que vous ne libérez pas, définissez-la comme nulle dans la méthode dealloc. Si vous lui définissez copy, vous devez le libérer.

EDIT

Vous avez dit: * Mais supposons que j'ai cette *

@property (nonatomic, retain) UIView *myView; 

et

myView = [[UIView alloc] initWithFrame:myFrame]; 
[self.view addSubview:myView]; 
[myView release]; 

? Je libère déjà myView ... dois-je le relâcher ???

Tout d'abord, puisque vous avez votre propriété définie de cette façon, vous devriez avoir la méthode dealloc comme:

- (void) dealloc{ 
    [myView release]; 
    [super dealloc]; 
} 

Donc, la réponse est NON, vous ne devriez pas le libérer, mais est en fait pas correct. S'il vous plaît jeter un oeil:

myView = [[UIView alloc] initWithFrame:myFrame]; //myView retainCount is 1 
[self.view addSubview:myView]; //retainCount is 2 
[myView release]; //retainCount is 1 again 

plus tard dans la méthode dealloc

- (void) dealloc{ 
    [myView release]; // retainCount becomes 0, is deallocated 
    [super dealloc]; // subviews of self.view are released but myView was already deallocated!, so you have over released myView once ;(
} 

Ceci est la façon correcte: (Utilisez vos propriétés;))

UIView *aView = [[UIView alloc] initWithFrame:myFrame]; // init, retainCount is 1 
self.myView = aView; // retainCount becomes 2 
[aView release]; // retainCount becomes 1 again and we are fine. 

[self.view addSubview:self.myView]; //retainCounts becomes 2 again. 

même si elle est 2 là Il n'y a pas de problème car lorsque self.view est libéré, ses sous-vues seront également libérées. Ainsi self.myView retainCount redeviendra 1 plus tard lorsque le self sera désalloué.

- (void) dealloc{ 
    [myView release]; //retainCounts becomes 1 
    [super dealloc]; // all its subviews of self.view are released hence myView retaincount becomes 1 and is released corretly 
} 

Quelle est la différence?

self.myView Supposer également retenu par un autre objet X et avec l'ancienne approche, le point de vue de X pointer vers un objet non valide, car il était déjà sorti.

Hope it helps

EDIT2 Comme indication de bbum, c'est un mini-mini-short tutoriel sur les propriétés:

lorsque vous avez

@property (... retain) NSObject *retainVar; 
@property (... assign) NSObject *assignVar; 
@property (... copy) NSObject *copyVar; 

et vous @synthesize les

est comme avoir les setters suivants:

// retain 
-(void)setRetainVar:(NSObject *)var { 
    if (retainVar != var) { 
     [retainVar release]; 
     retainVar = [var retain]; 
    } 
} 
//assign 
-(void)setAssignVar:(NSObject *)var { 
    assignVar = var; 
} 
//copy 
-(void)setCopyVar:(NSObject *)var { 
    if (copyVar != var) { 
     [copyVar release]; 
     copyVar = [var copy]; 
    } 
} 

(cela signifie que si vous attribuez directement un objet que vous devez vous assurer est quelque chose d'équivalent à setters ci-dessus, du point de vue de la gestion de la mémoire)

et votre méthode dealloc devrait être quelque chose comme :

- (void) dealloc{ 
    [retainVar release]; 
    assignVar = nil; 
    [copyVar release]; 
    [super dealloc]; 
} 

Lors du réglage de votre Ivars

par exemple, à l'intérieur de iNIT:

- (id) init{ 
    if ((self = [super init])){ 

     //this is ok 
     retainVar = [[NSObject alloc] init];//but is retainVar was not nil we will have a leak ;(

     //This is better 
     NSObject *obj = [NSObject alloc] init]; 
     self.retainVar = obj; 
     [obj release]; 

     //this is BAD 
     assignVar = [[NSObject alloc] init];//because this is like retaining it, later it will leak 

     //below is correct 
     NSObject *obj = [[[NSObject alloc] init] autorelease]; 
     assignVar = obj; 

     //copy is pretty much like retain, 
     //this is ok 
     copyVar = [[NSObject alloc] init]; //but, if copyVar was not nil is a leak! 

     //below is better 
     NSObject *obj = [NSObject alloc] init]: 
     self.retainVar = obj; 
     [obj release]; 

    } 
    return self; 
} 
+1

Vous devez discuter de la différence entre les deux. Définir directement les variables d'instance et le faire par l'intermédiaire du setter/getter en ce qui concerne la conservation/libération. Tel qu'il est, c'est trompeur. – bbum

+0

@bbum - pouvez-vous créer une réponse expliquant ce que vous voulez dire? – SpaceDog

+0

@ nacho4d - libération, non? Mais supposons que j'ai cette propriété @ (nonatomic, retain) UIView * myView; sur .h puis sur .m j'ai myView = [[UIView alloc] initWithFrame: myFrame]; [self.view addSubview: myView]; [version myView]; ? Je libère déjà myView ... dois-je le relâcher ??? – SpaceDog