2012-06-19 4 views
5

que escribió el código de ejemplo para ver cómo funciona ARC¿Por qué las propiedades débiles de NSString no se liberan en iOS?

@property (nonatomic, weak) NSString *myString; 
@property (nonatomic, weak) NSObject *myObj; 
@end 

@implementation ViewController 
@synthesize myString = _myString; 
@synthesize myObj = _myObj; 
- (void) viewDidAppear:(BOOL)animated 
{ 
    NSLog(@"Appearing Obj: !%@!",self.myObj); 
    NSLog(@"Appearing String: !%@!",self.myString); 
} 

- (void)viewDidLoad 
{ 
    self.myObj = [[NSObject alloc] init]; 
    self.myString = [[NSString alloc] init]; 
    NSLog(@"Loading Obj %@",self.myObj); 
    NSLog(@"Loading String: !%@!",self.myString); 
} 

Sin embargo, sorprendentemente me dieron estos resultados:

2012-06-19 15:08:22.516 TESTER[4041:f803] Loading Obj (null) 
2012-06-19 15:08:22.517 TESTER[4041:f803] Loading String: !! 
2012-06-19 15:08:22.533 TESTER[4041:f803] Appearing Obj: !(null)! 
2012-06-19 15:08:22.535 TESTER[4041:f803] Appearing String: !! 

Como se puede ver, Obj fue liberada correctamente, pero mi cadena (que es también una propiedad débil) no imprime nulo ... ¿Por qué no?

+0

¿Es la cadena que está configurando en 'myString' por cualquier cambio una cadena literal (algo así como @" Hello world! ")? –

Respuesta

12

NSString utiliza todo tipo de trucos internos para reutilizar objetos y evitar asignaciones y copias innecesarias. Puede hacerlo porque las instancias NSString son inmutables. En este caso, probablemente exista una instancia compartida para representar una cadena vacía que devuelve [[NSString alloc] init], y esta instancia compartida se retendrá en otro lugar como singleton.

+0

Eso parece tener sentido. ¡Gracias! – Nosrettap

+0

Quizás alguien pueda verificar el código fuente de NSString para confirmar esto. –

+0

Tiene sentido, aunque no creo que sea sabio confiar en este comportamiento, que parece ser solo una manifestación de alguna optimización, que está sujeta a cambios en una fecha futura. – Rob

6

[[NSString alloc] init] siempre devuelve idéntico valor. Puede verificarlo usted mismo.

NSString *string1 = [[NSString alloc] init]; 
NSString *string2 = [[NSString alloc] init]; 
NSString *string3 = [[NSString alloc] init]; 
NSLog(@"string1 = %p, string2 = %p, string3 = %p", string1, string2, string3) 

Este código devuelve tres direcciones idénticas. En mi caso, la producción fue:

string1 = 0x3e8dd74c, string2 = 0x3e8dd74c, string3 = 0x3e8dd74c 

Eso significa [[NSString alloc] init] vuelve Singleton. Los singletons usualmente no pueden ser liberados.

Hacer cadenas con otros métodos (como initWithFormat:) hace objetos usuales 'no únicos', que generalmente se pueden liberar , con algunas excepciones.

adicional: Buscando código fuente (ensamblador):

-[NSPlaceholderString init]: 
00040ea4  f64b009c  movw r0, 0xb89c 
00040ea8  f2c00016  movt r0, 0x16 
00040eac   4478  add  r0, pc 
00040eae   4770  bx  lr 

sería algo como esto (en objectivec)

-(id)init 
{ 
    return SOME_CONSTANT_VALUE; 
} 

Podría ser kCFEmptyString, pero no estoy Por supuesto.

Cuestiones relacionadas