Управление памятью в Objective-C
Управление памятью является основной концепцией независимо от языка программирования. Процесс выделения памяти объектов, когда они необходимы, и освобождения, когда они больше не используются, называется управлением памятью . Память — ограниченный ресурс, поэтому с ней нужно обращаться осторожно. Если ненужная память не освобождается постепенно, у вас заканчивается память, что приводит к снижению производительности вашего компьютера, а в худшем случае это может даже привести к сбою вашего компьютера. Эффективное управление памятью связано с экономией времени, затрат и ресурсов, которых можно добиться в Objective-C.
В Objective-C память управляется следующим образом:
- MRR (ручное сохранение)
- ARC (автоматический подсчет ссылок)
Ручной фиксатор (MRR)
MRR (Manual Retain Release) также известен как ручной подсчет ссылок (MRC). В Objective-C все классы являются производными от корневого класса NSObject (здесь NS означает NeXTSTEP), который предоставляет методы для управления памятью. Все классы NSObject имеют счетчик ссылок, т.е. объекты отслеживают, сколько раз на них ссылается другой объект. Когда счетчик ссылок становится равным нулю, объект умирает, а память освобождается.
Retain (счетчик ссылок ++) и Release (счетчик ссылок -) — это специальные методы, которые используются для отслеживания счетчика ссылок, где метод Retain увеличивает значение счетчика ссылок на 1, а метод Release уменьшает значение счетчика ссылок на 1. .
Согласно методу MRR, мы напрямую управляем памятью, выделяя и освобождая ее вручную. Следовательно, если объект создан, он не умрет, пока мы его не уничтожим. В случае, если мы создадим объект и забудем уничтожить или освободить объект, это вызовет утечку памяти. У нас может закончиться память, если она продолжит утечку.
МРР ОСНОВНЫЕ ПРАВИЛА
В MRR, как следует из названия, все делается вручную: создание объекта, доступ к нему, сохранение объекта, его освобождение и уничтожение объекта. Поэтому во избежание утечки памяти и для точного отслеживания счетчика ссылок следует помнить несколько основных правил:
- Тот, кто создает объект, является владельцем самого объекта . Методы «alloc», «new», «copy» или «mutableCopy» используются для создания объекта и подразумевают, что вы также являетесь владельцем объекта.
- Можно владеть объектом, используя метод сохранения . Иногда методы, отличные от «alloc», «new», «copy» или «mutableCopy», возвращают объект, в этом случае, поскольку вы не создавали объект и поэтому не являетесь его владельцем. Но владение может быть достигнуто с помощью метода «сохранения», как если бы вы получили объект с помощью метода «аллок» / «новый» / «копировать» или «мутаблекопи». Кроме того, если объект удерживается x раз, то он должен быть освобожден x раз.
- Необходимо отказаться от права собственности на объект, которым он владеет, с помощью метода освобождения или автоматического освобождения, когда объект больше не используется. Метод освобождения освобождает объект немедленно, тогда как метод автоматического освобождения не освобождает объект немедленно, а отправляет его в пул автоматического освобождения и освобождает объект, когда пул опустошается.
- Нельзя освобождать объект, которым не владеют . Освобождение объекта, которым мы не владеем, может привести к сбою приложения. Сбой может произойти в случаях, когда мы освобождаем или обращаемся к уже уничтоженному объекту.
Жизненный цикл объекта класса X представлен на приведенной выше диаграмме вместе с правильной реализацией правил:
Объект класса X был создан с использованием метода «alloc»/«init», предоставленного в классе NSObject. по мере создания объекта счетчик ссылок становится равным 1 (правило 1).
Некоторые классы Y обращаются к объектам класса X. Поскольку класс Y не владеет объектом, для получения объекта используется метод «retain». Поскольку используется метод сохранения, он увеличивает значение счетчика ссылок на 1, обновляя значение счетчика ссылок до 2 (Правило 2).
Объект класса X был дважды сохранен двумя разными классами, и поэтому для уничтожения объекта и достижения нулевого счетчика ссылок его необходимо дважды освободить. Во-первых, счетчик ссылок, который в настоящее время равен 2, уменьшается на 1, когда класс X освобождает объект, и становится равным 1. Наконец, когда класс Y освобождает объект, счетчик ссылок становится равным нулю, уничтожая объект (правило 3).
Далее класс Z создал еще один объект, который является копией объекта класса X. Здесь создается новый объект с теми же переменными экземпляра, что и у объекта класса X, счетчик ссылок становится равным 1 (правило 1).
Класс Z использовал метод освобождения, который уменьшает значение счетчика ссылок на 1. При уменьшении значение счетчика ссылок становится равным нулю, а объект класса Z уничтожается (правило 3).
ObjectiveC
#import<Foundation/Foundation.h> @interface my_class: NSObject -( void )my_method; @end @implementation my_class -( void )my_method{ NSLog ( @"It"s gonna be allocated
" ); } -( void )dealloc{ NSLog ( @"Everything"s cleaned up
" ); [ super dealloc]; } @end int main() { // some_object_gfg has been created my_class *some_object_gfg=[[my_class alloc]init]; [some_object_gfg my_method]; // Reference count = 1 NSLog ( @"Reference count after allocation :%d" ,[some_object_gfg retainCount]); [some_object_gfg retain]; // Reference count = 1+1 = 2 NSLog ( @"Reference count after retain :%d" ,[some_object_gfg retainCount]); [some_object_gfg release]; // Reference count = 2-1 = 1 NSLog ( @"Reference count after release :%d" ,[some_object_gfg retainCount]); [some_object_gfg release]; some_object_gfg = nil ; // Reference count = 0 // Object destroyed return 0; } |
Выход:
2022-11-28 08:07:12.546 main[55731] It"s gonna be allocated ;) 2022-11-28 08:07:12.546 main[55731] Reference count after allocation :1 2022-11-28 08:07:12.546 main[55731] Reference count after retain :2 2022-11-28 08:07:12.546 main[55731] Reference count after release :1 2022-11-28 08:07:12.546 main[55731] Everything"s cleaned up :)
Автоматический подсчет ссылок (ARC)
ARC (автоматический подсчет ссылок) был представлен Apple Inc. в 2011 году для разработки приложений для своих настольных и мобильных ОС, Mac OS X Lion и iOS 5. ARC — это более продвинутый, удобный и автоматический способ управления памятью. Сам ARC вставляет надлежащие вызовы управления памятью, такие как сохранение, освобождение и автоматическое освобождение, для пользователей во время компиляции в зависимости от использования. Он также следует тем же основным правилам, которые обсуждались выше, но с небольшими изменениями, такими как квалификаторы владения. Это сокращает объем кода, поскольку разработчику не нужно писать каждое сохранение или выпуск. Это также сводит к минимуму риск утечки памяти, поскольку компилятор оценивает срок службы самого объекта. Методы Retain, Release, AutoRelease или KeepCount работают только с MRR, но не с ARC. Также ошибки появляются, если мы используем NSAutoreleasePool вместо блока @autoreleasepool. Принцип сборки мусора доступен только для Mac OS X, начиная с версии 10.5. Кроме того, приложения iOS не могут использовать сборку мусора, поскольку это зависит от мощности устройства, обработка займет некоторое время, что заставит пользователя ждать, что приведет к плохому взаимодействию с пользователем. Он также устарел, поскольку в OS X версии 10.8 используется ARC, и его планируется удалить в следующих версиях OS X. ARC не является службой времени выполнения. Он не следует шаблону выполнения программы сборки мусора. Apple говорит: «ARC в Objective-C делает управление памятью работой компилятора».
ObjectiveC
#import<Foundation/Foundation.h> @interface my_class: NSObject -( void )my_method; @end @implementation my_class -( void )my_method{ NSLog ( @"Using ARC :
" ); } -( void )dealloc{ NSLog ( @"Everything"s cleaned up
" ); [ super dealloc]; } @end int main() { @autoreleasepool { // Compiler takes care of retain , release or // autorelease itself as it is automatic my_class *some_object_gfg = [my_class[alloc]init]; [some_object_gfg my_method]; some_object_gfg = nil ; } return 0; } |
Примечание. Этот код не будет работать на онлайн-компиляторе, поскольку он не поддерживает ARC.
Выход: