2012-06-19 19 views
5

Napisałem następujący kod przykładowy, aby zobaczyć, jak ARC działaDlaczego słabe właściwości NSString nie są wydawane w systemie 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); 
} 

Jednak zaskakująco mam te wyniki:

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: !! 

Jak widać, Obj został prawidłowo wydany ale mój ciąg (który jest również słaba właściwość) nie drukuje null ... Dlaczego nie?

+0

Czy ciąg, który ustawiasz w 'myString' przez jakąkolwiek zmianę literału łańcuchowego (coś w stylu @" Hello world! ")? –

Odpowiedz

12

wykorzystuje różnego rodzaju wewnętrzne oszustwo do ponownego użycia obiektów i uniknięcia niepotrzebnych przydziałów i kopii. Może to zrobić, ponieważ instancje NSString są niezmienne. W tym przypadku prawdopodobnie istnieje współużytkowana instancja reprezentująca pusty łańcuch, który jest zwracany przez [[NSString alloc] init], a ta współużytkowana instancja zostanie zachowana gdzie indziej jako singleton.

+0

To wydaje się mieć sens. Dzięki! – Nosrettap

+0

Być może ktoś może sprawdzić kod źródłowy NSString, aby to potwierdzić. –

+0

Ma sens, chociaż nie sądzę, że rozsądnie byłoby polegać na tym zachowaniu, które wydaje się być jedynie przejawem optymalizacji, która może ulec zmianie w przyszłości. – Rob

6

[[NSString alloc] init] zawsze zwraca wartość identyczną. Możesz to sprawdzić sam.

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) 

Ten kod zwraca trzy identyczne adresy. W moim przypadku było wyjście:

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

Oznacza to [[NSString alloc] init] powraca Singleton. Singleton zazwyczaj nie może zostać uwolniony.

Wykonywanie ciągów za pomocą innych metod (np. initWithFormat:) tworzy zwykłe obiekty "nie singleton", które zwykle można zwolnić , z pewnymi wyjątkami.

dalej: Patrząc kod źródłowy (Assembler):

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

byłoby coś takiego (w ObjectiveC)

-(id)init 
{ 
    return SOME_CONSTANT_VALUE; 
} 

Może być kCFEmptyString, ale nie jestem pewnie.

Powiązane problemy