Вопрос по automatic-ref-counting, iphone, ios, objective-c – Почему слабые свойства NSString не выпускаются в iOS?

5

Я написал следующий пример кода, чтобы увидеть, как работает ARC

@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);
}

Однако на удивление я получил эти результаты:

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

Как вы можете видеть, Obj был выпущен правильно, но моя строка (которая также является слабым свойством) не выводит ноль ... Почему бы и нет?

Строка, в которую вы устанавливаетеmyString при любом изменении строкового литерала (что-то вроде @ & quot; Hello world! & quot;)? David Rönnqvist

Ваш Ответ

2   ответа
12

NSString использует всевозможные внутренние хитрости, чтобы повторно использовать объекты и избегать ненужных выделений и копий. Это может сделать это, потому чтоNSString экземпляры неизменны. В этом случае, вероятно, существует общий экземпляр, представляющий пустую строку, которая возвращается[[NSString alloc] init]и этот общий экземпляр будет сохранен где-то еще как одиночный.

Кажется, это имеет смысл. Спасибо! Nosrettap
Я предполагаю, что copy также выдаст тот же общий экземпляр, когда вы вызываете его в буквальной строке?
Возможно, кто-нибудь может проверить исходный код NSString, чтобы подтвердить это.
Имеет смысл, хотя я не думаю, что было бы разумно полагаться на это поведение, которое, кажется, просто проявление некоторой оптимизации, которая может измениться в будущем.
Одной из таких оптимизаций является то, что строковые литералы существуют в течение всего времени жизни приложения. Кроме того, создание новой строки со ссылкой на строковый литерал ([NSString stringWithFormat:@"Hello world"]; или же[[NSString alloc] initWithFormat:@"Hello world"];) вернет ссылку на точно такой же строковый литерал (как я упоминал вmy answer)
6

[[NSString alloc] init] всегда возвращаетсяidentical значение. Вы можете проверить это самостоятельно.

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

Этот код возвращает три одинаковых адреса. В моем случае вывод был:

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

Это означает[[NSString alloc] init] возвращаетсяSingleton, Синглтоны обычно не могут быть освобождены.

Создание строк с другими методами (например,initWithFormat:) делает обычным «не синглтон»; объекты, которые обычноcan be releasedс некоторыми исключениями.

Further: Ищем исходный код (Ассемблер):

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

это было бы что-то вроде этого (в ObjectiveC)

-(id)init
{
    return SOME_CONSTANT_VALUE;
}

Это может бытьkCFEmptyString, но я не уверен.

Похожие вопросы