Чи потрібно використовувати автореліз в програмі Swift?


95

На сторінці 17 цієї презентації WWDC14 сказано

Робота з Objective-C? Все одно доведеться керувати пулами
автовипуску autoreleasepool {/ * код * /}

Що це означає? Чи означає це, що якщо в моїй базі коду немає файлів Objective-C, autoreleasepool {}це непотрібно?

У відповіді на відповідне запитання є приклад, де autoreleasepoolможе бути корисно:

- (void)useALoadOfNumbers {
    for (int j = 0; j < 10000; ++j) {
        @autoreleasepool {
            for (int i = 0; i < 10000; ++i) {
                NSNumber *number = [NSNumber numberWithInt:(i+j)];
                NSLog(@"number = %p", number);
            }
        }
    }
}

Якщо вищевказаний код буде переведений на Swift зі autoreleasepoolскинутим, чи буде Swift досить розумним, щоб знати, що numberзмінну слід випустити після першої }(як це робить деякі інші мови)?


1
Здається, autoreleasepoolу Swift немає документації . Я розширив ваше запитання і задав його на форумах розробників .
Аарон Брагер

Відповіді:


197

autoreleasepoolШаблон використовується в Swift при поверненні autoreleaseоб'єктів (створених або кодом Objective-C або з допомогою класів какао). autoreleaseШаблон у функції Swift багато , як це робить в Objective-C. Наприклад, розглянемо це Swift-передавання вашого методу (створення екземпляра NSImage/ UIImageobjects):

func useManyImages() {
    let filename = pathForResourceInBundle

    for _ in 0 ..< 5 {
        autoreleasepool {
            for _ in 0 ..< 1000 {
                let image = NSImage(contentsOfFile: filename)
            }
        }
    }
}

Якщо це запустити в інструментах, ви побачите графік розподілу на зразок наступного:

з автореліз-пулом

Але якщо ви зробите це без пулу автовипуску, ви побачите, що пікове використання пам'яті вище:

без автореліз-пулу

autoreleasepoolДозволяє явно управляти , коли autorelease об'єкти вивільнені в Swift, так само , як ви були в стані в Objective-C.

Примітка. Під час роботи з нативними об'єктами Swift, як правило, ви не отримаєте об'єктів автовипуску. Ось чому в презентації згадується застереження про необхідність цього лише під час "роботи з Objective-C", хоча я б хотів, щоб Apple в цьому питанні була більш зрозумілою. Але якщо ви маєте справу з об'єктами Objective-C (включаючи класи какао), вони можуть бути об'єктами автоматичного випуску, і в цьому випадку ця швидка передача @autoreleasepoolшаблону Objective-C все ще корисна.


2
З усіх цих питань ви можете написати свій власний клас і зробити його printlnв deinit, і перевірити, коли об’єкти розміщені, стає досить просто. Або спостерігати за цим у інструментах. У відповідь на ваше запитання виявляється, що об'єкти Swift повертаються з функцій з +1 утримувати кількість рахунків (не об'єкти автовипуску), і абонент безперешкодно керує правом власності з цієї точки (наприклад, якщо і коли повернутий об'єкт випадає з сфери дії, його негайно розміщують, не розміщують в авторелізі).
Роб

3
@StevenHernandez Пул автоматичного випуску має дуже мало спільного з витоками. Витік спричинений невипущеним об'єктом. З іншого боку, пул автоматичного випуску - це лише сукупність об'єктів, для яких відкладено випуск до вичерпання пулу. Басейни не контролюють, чи є щось розміщене чи ні, а просто просто терміни такого розселення. Переглянувши перегляд карти, ви не можете контролювати, що робить кешування (використовує пам’ять, але не справжній витік), а також не робити нічого, якщо був реальний витік (і я не знаю про значні витоки подання карти, хоча історично було випадкові, помірні витоки в UIKit).
Роб

2
@matt Так, я бачив подібну поведінку. Тож я повторив свою вправу з NSImage/ UIImageobjects і проявляв проблему більш послідовно (і, чесно кажучи, це більш поширений приклад проблеми, оскільки пікове використання пам'яті часто є проблематичним лише при роботі з більшими об'єктами; практичним прикладом цього може бути рутинна зміна розміру групи зображень). Я також відтворив поведінку, що викликає код Objective-C, який явно створював об'єкти автоматичного випуску. Не зрозумійте мене неправильно: я думаю, що нам потрібні пуфи для автоматичного випуску в Swift рідше, ніж у Objective-C, але це все ще має роль.
Роб

1
Я знайшов приклад, який працює! Просто зателефонуйте до NSBundle pathForResource:ofType:.
мат

1
Мій pathForResource:ofType:приклад більше не працює в Xcode 6.3 / Swift 1.2. :)
matt

4

Якщо ви використовуєте його в еквівалентному коді Objective-C, то ви використовували б його в Swift.

чи буде Свіфт досить розумним, щоб знати, що змінну числа слід звільнити після першої}

Тільки якщо це робить Objective-C. Обидва діють відповідно до правил управління пам’яттю Cocoa.

Звичайно, ARC знає, що це numberвиходить за межі обсягу в кінці цієї ітерації циклу, і якщо він його збереже, він випустить його там. Однак це не говорить вам, чи було автоматично випущено об’єкт, оскільки -[NSNumber numberWithInt:] він може повернути екземпляр автоматичного випуску чи ні . Ви не можете знати, оскільки у вас немає доступу до джерела -[NSNumber numberWithInt:].


1
Якщо Свіфт для цього поводиться так само, як Objective-C, чому в презентації згадується "Робота з Objective-C?" конкретно?
Етан

9
@Ethan Здавалося б, власні об'єкти Swift не є об'єктами автоматичного випуску, і autoreleasepoolконструкція абсолютно непотрібна. Але якщо ваш код Swift обробляє об'єкти Objective-C (включаючи об'єкти какао), вони дотримуються шаблонів автоматичного випуску, і таким чином autoreleasepoolконструкція стає корисною.
Роб

Я розумію, що "Autoreleasepool дозволяє вам чітко керувати, коли об'єкти авторелізингу розміщені в Swift", але чому я цього хочу? Чому компілятор не може / не може зробити це за мене? Мені довелося додати власний авторелізпул, щоб ВМ не перебирав дах у тісному циклі величезних маніпуляцій із струнами. Мені було очевидно, куди його слід додати, і це справно працювало. Чому компілятор не міг цього зробити? Чи міг би компілятор зробити розумнішим, щоб добре зробити це?
vonlost
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.