Автоматический подсчет ссылок - Automatic Reference Counting

Автоматический подсчет ссылок ( ARC ) - это функция управления памятью компилятора Clang, обеспечивающая автоматический подсчет ссылок для языков программирования Objective-C и Swift . Во время компиляции, он вставляет в код объекта сообщений , и которые увеличивают и уменьшают количество ссылок во время выполнения, маркировка для открепления этих объектов , когда число ссылок на них достигает нуля. retainrelease

ARC отличается от трассировки сборки мусора отсутствием фонового процесса, который асинхронно освобождает объекты во время выполнения. В отличие от трассировки сборки мусора, ARC не обрабатывает циклы ссылок автоматически. Это означает, что пока существуют «сильные» ссылки на объект, он не будет освобожден. Соответственно, сильные перекрестные ссылки могут создавать взаимоблокировки и утечки памяти . Разработчик должен разорвать циклы, используя слабые ссылки .

Apple Inc. развертывает ARC в своих операционных системах, таких как macOS ( OS X ) и iOS . Ограниченная поддержка (ARCLite) доступна начиная с Mac OS X Snow Leopard и iOS 4 , а полная поддержка - в Mac OS X Lion и iOS 5 . Сборка мусора была объявлена ​​устаревшей в OS X Mountain Lion в пользу ARC и удалена из библиотеки времени выполнения Objective-C в macOS Sierra .

Цель-C

Когда ARC включен, компилятор применяет следующие правила:

  • retain, release, retainCount, autoreleaseИли deallocне могут быть отправлены на объекты. Вместо этого компилятор автоматически вставляет эти сообщения во время компиляции, в том числе [super dealloc]при deallocпереопределении.
    // Without ARC
    - (void)dealloc
    {
       [[NSNotificationCenter defaultCenter] removeObserver:self];
       [super dealloc];
    }
    
    // With ARC
    - (void)dealloc
    {
       [[NSNotificationCenter defaultCenter] removeObserver:self];
       // [super dealloc] is called automatically
    }
    
  • Программы не могут выполнять прямое преобразование между idи void *. Это включает преобразование между объектами Foundation и объектами Core Foundation. Программы должны использовать специальные преобразования типов или вызовы специальных функций, чтобы сообщить компилятору больше информации о времени жизни объекта.
    // Without ARC
    - (NSString *)giveMeAString
    {
        CFStringRef myString = [self someMethodThatCreatesACFString];
        NSString *newString = (NSString *)myString;
        return [newString autorelease];
    }
    
    // With ARC
    - (NSString *)giveMeAString
    {
        CFStringRef myString = [self someMethodThatCreatesACFString]; // retain count is 1
        NSString *newString = (__bridge_transfer NSString *)myString; // the ownership has now been transferred into ARC
        return newString;
    }
    
  • Пул с автоматическим освобождением может использоваться для временного выделения объектов и сохранения их в памяти до тех пор, пока пул не будет «истощен». Без ARC NSAutoreleasePoolдля этой цели можно создать объект. @autoreleasepoolВместо этого ARC использует блоки, которые инкапсулируют выделение временных объектов и освобождают их, когда достигается конец блока.
    // Without ARC
    - (void)loopThroughArray:(NSArray *)array
    {
        for (id object in array) {
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
            // Create a lot of temporary objects
            [pool drain];
        }
    }
    
    // With ARC
    - (void)loopThroughArray:(NSArray *)array
    {
        for (id object in array) {
            @autoreleasepool {
                // Create a lot of temporary objects
            }
        }
    }
    
  • Программы не могут вызывать функции NSAllocateObjectиNSDeallocateObject
  • Программы не могут использовать объектные указатели в структурах C ( structы)
  • Программы не могут использовать зоны памяти ( NSZone)
  • Чтобы правильно взаимодействовать с кодом, отличным от ARC, программы не должны использовать никаких методов или объявленных свойств (если явно не выбран другой получатель), которые начинаются с new.

Декларации собственности

ARC вводит некоторые новые атрибуты объявления свойств, некоторые из которых заменяют старые атрибуты.

Без ARC С ARC С ARCLite
retain strong
assign (для типов объектов) weak unsafe_unretained
copy

Обнуление слабых ссылок

Обнуление слабых ссылок - это функция в Objective-C ARC, которая автоматически очищает (устанавливает nil) локальные переменные со слабыми ссылками, переменные экземпляра и объявленные свойства непосредственно перед тем, как объект, на который указывается, начинает освобождаться. Это гарантирует, что указатель идет либо на действительный объект, либо nil, и позволяет избежать висящих указателей . До введения этой функции «слабые ссылки» относились к ссылкам, которые не сохранялись, но не были установлены, nilкогда объект, на который они указывали, был освобожден (эквивалентно unsafe_unretainedв ARC), что могло привести к зависанию указателя. Обычно программист должен был убедиться, что все возможные слабые ссылки на объект были установлены на ноль вручную при его освобождении. Обнуление слабых ссылок устраняет необходимость в этом.

Обнуление слабых ссылок указывается с помощью объявленного атрибута свойства weak или с помощью атрибута переменной __weak.

Обнуление слабых ссылок доступно только в Mac OS X Lion (10.7) или новее и iOS 5 или новее, поскольку они требуют дополнительной поддержки со стороны среды выполнения Objective-C. Однако некоторые классы OS X в настоящее время не поддерживают слабые ссылки. Код, который использует ARC, но должен поддерживать более старые версии ОС, чем указанные выше, не может использовать обнуление слабых ссылок и, следовательно, должен использовать unsafe_unretainedслабые ссылки. Существует сторонняя библиотека PLWeakCompatibility [1], которая позволяет использовать обнуление слабых ссылок даже в этих более старых версиях ОС.

Преобразование в

Xcode 4.2 или новее предоставляет способ конвертировать код в ARC. Начиная с Xcode 4.5, его можно найти, выбрав Edit> Refactor> Convert to Objective-C ARC ... Хотя Xcode автоматически конвертирует большую часть кода, некоторые коды, возможно, придется преобразовать вручную. Xcode сообщит разработчику, когда возникают более сложные варианты использования, например, когда переменная объявляется внутри пула автозапуска и используется вне его, или когда два объекта необходимо соединить бесплатно с помощью специальных преобразований.

Swift

В Swift ссылки на объекты сильны, если они не объявлены weakили unowned. Swift требует явной обработки nil с необязательным типом: тип значения, который может иметь значение или быть nil. Необязательный тип должен обрабатываться путем «разворачивания» его с помощью условного оператора , позволяющего безопасно использовать значение, если оно есть. И наоборот, любой необязательный тип всегда будет иметь значение и не может быть нулевым.

var myString: String                   // Can only be a string
var myOtherString: String?             // Can be a string or nil

if let myString = myOtherString {      // Unwrap the Optional
    print(myString)                    // Print the string, if present 
}

Соответственно, сильная ссылка на объект не может иметь тип Optional, поскольку объект будет храниться в куче, пока сама ссылка не будет освобождена. Слабая ссылка имеет тип Необязательный, поскольку объект может быть освобожден, а для ссылки может быть установлено значение nil. Необязательные ссылки попадают между ними; они не являются ни сильными, ни опциональными. Вместо этого компилятор предполагает, что объект, которому не принадлежат контрольные точки, не освобождается, пока сама ссылка остается выделенной. Обычно это используется в ситуациях, когда целевой объект сам содержит ссылку на объект, который содержит ссылку без владельца.

var strongReference: MyClass          // Strong reference, cannot be nil
weak var weakReference: MyClass?      // Weak reference, can be nil
unowned var unownedReference: MyClass // Weak reference, cannot be nil

Swift также отличается от Objective-C в использовании и поощрении типов значений вместо ссылочных типов . Большинство типов в стандартной библиотеке Swift являются типами значений, и они копируются по значению, тогда как классы и замыкания являются ссылочными типами и передаются по ссылке. Поскольку типы значений копируются при передаче, они автоматически освобождаются со ссылкой, которая их создала.

Смотрите также

Ссылки

внешние ссылки