Почему слабые свойства 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
, но я не уверен.