Какое волшебное управление памятью происходит внутри класса NSString? - PullRequest
0 голосов
/ 26 августа 2018

Я пытаюсь сделать много временных объектов внутри цикла for, как показано ниже:

- (void)viewDidLoad {
    [super viewDidLoad];
    for (NSInteger i=0; i<NSIntegerMax; i++) {
        NSString* str = [[NSString alloc]initWithFormat:@"%ld",(long)i];
        NSLog(@"Address:0x%x, String:%@",(unsigned int)str,str);
    }
}

, но память остается очень устойчивой с классом NSString или NSMutableString. Однако, если я изменю класс на UILabel или другие классы, память увеличится невероятно быстро.

- (void)viewDidLoad {
    [super viewDidLoad];
    for (NSInteger i=0; i<NSIntegerMax; i++) {
        UILabel* label = [[UILabel alloc]init];
        NSLog(@"Address:0x%x, String:%@",(unsigned int)label,label);
    }
}

Я даже оборачиваю свой код в пул автоматического выпуска, но кажется, что пул автоматического выпуска не имеет никакого смысла.

- (void)viewDidLoad {
    [super viewDidLoad];
    for (NSInteger i=0; i<NSIntegerMax; i++) {
        @autoreleasepool{
        UILabel* label = [[UILabel alloc]init];
        NSLog(@"Address:0x%x, String:%@",(unsigned int)label,label);
        }
    }
}

Но для класса NSString даже без пула автоматического выпуска память остается очень стабильной и, кажется, никогда не будет расти. Я очень смущен этим явлением и надеюсь, что кто-нибудь сможет объяснить мне, почему это происходит. Спасибо.

1 Ответ

0 голосов
/ 14 сентября 2018

В этом нет ничего «волшебного» - ни в одном из вышеперечисленных фрагментов кода нет ничего, что определенно необходимо было бы автоматически выпустить (и на самом деле это, вероятно, верно для любого фрагмента кода, написанного на ARC).Переменная str или label сохраняется на alloc, а затем освобождается в конце этой области в конце каждой итерации цикла for.

Однако эти классы (NSString, UILabel и т. Д.) Реализуются системной библиотекой, и мы не знаем, что делают их методы внутренне.Они могут делать авто-релизы, а могут и не делать.

Если это делает авто-релизы внутри методов, тогда завершение вызовов в @autoreleasepool должно привести к тому, что что-либо автоматически выпущенное внутри будет освобождено.Однако размещение объектов в пуле автоматического выпуска - не единственный способ увеличения памяти.Вместо этого они могут помещать вещи в какой-то кеш, где он хранится и не освобождается (до некоторого более позднего момента, когда кеш очищается).Это израсходует память и не будет освобождено в конце пула автоматического выпуска.

...