objective-c 2.0 proprietà e 'mantenere'
-
19-09-2019 - |
Domanda
Domanda stupida, ma perché abbiamo bisogno di utilizzo di 'trattenere' quando la dichiarazione di una proprietà?Non avere mantenuto in ogni caso quando si è ricevuto qualcosa?
Guardando a questo esempio, sembra che un oggetto viene automaticamente mantenuta quando alloc sotto, così che cosa è il punto?
#import "Fraction.h"
#import <stdio.h>
int main( int argc, const char *argv[] ) {
Fraction *frac1 = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
// print current counts
printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );
// increment them
[frac1 retain]; // 2
[frac1 retain]; // 3
[frac2 retain]; // 2
// print current counts
printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );
// decrement
[frac1 release]; // 2
[frac2 release]; // 1
// print current counts
printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );
// release them until they dealloc themselves
[frac1 release]; // 1
[frac1 release]; // 0
[frac2 release]; // 0
■uscita
Frazione 1 retain count:1
Frazione 2 retain count:1
Frazione 1 retain count:3
Frazione 2 retain count:2
Frazione 1 retain count:2
Frazione 2 retain count:1
Deallocing frazione
Deallocing frazione
Questo mi sta facendo impazzire!
Soluzione
Il comportamento predefinito della proprietà è di ASSEGNARE, non CONSERVARE.Questi non sono lo stesso comportamento.Se la vostra proprietà è per un tipo di dati di base, come un int, quindi ASSEGNARE sarebbe corretto utilizzare.Tuttavia, se si specifica (mantenere) e la proprietà punta a un puntatore all'oggetto come NSObject *l'oggetto, il puntatore viene assegnato l'indirizzo di memoria dell'oggetto e mantenere il conteggio viene incrementato di uno.Se il programma si compone di niente di più che una singola funzione principale, quindi si fa fatica a vedere.Tuttavia, si supponga che la classe ha avuto questo metodo:
-(void)setMyArrayWithString:(NSString *)s{
myArray = [NSArray arrayWithObject:s];
}
Supponiamo myArray è definito come NSArray *myArray e ha la corretta @property (mantenere) istruzione.Tutto funziona bene fino a quando il metodo restituisce.Questo perché l'oggetto restituito da NSArray è un autoreleased oggetto.Se noi non lo si possiede, sarà rilasciato entro la NSAutoReleasePool e non saremo in grado di usarlo (e ci arriveremo un bug di brutto e il cattivo violazioni di accesso).Per risolvere questo problema è possibile fare due cose:
-(void)setMyArrayWithString:(NSString *)s{
self.myArray = [NSArray arrayWithObject:s];
// OR
myArray = [[NSArray arrayWithObject:s] retain];
}
La prima soluzione, che usa l'auto.myArray di utilizzare il @definizione di proprietà.Questo codice assegna e conserva quindi l'oggetto in modo da non perdere quando la funzione restituisce.La seconda soluzione imposta il NSArray *myArray puntatore manualmente manualmente e poi mantiene il NSArray oggetto.In entrambi i casi l'NSAutoreleasePool rilascerà l'oggetto alla fine della funzione, tuttavia non essere deallocato perché abbiamo ancora il nostro trattenere dal precedente mantenere viva.