Почему слабые свойства NSString не выпускаются в iOS?

Я написал следующий пример кода, чтобы увидеть, как работает 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 был выпущен правильно, но моя строка (которая также является слабым свойством) не выводит ноль... Почему бы и нет?

2 ответа

Решение

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

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

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)

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

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

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

Создание строк с другими методами (например, initWithFormat:) создает обычные "не-одиночные" объекты, которые обычно могут быть освобождены, за некоторыми исключениями.

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

-[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, но я не уверен.

Другие вопросы по тегам