Понимание управления памятью в IOS - PullRequest
0 голосов
/ 26 февраля 2012

Я нахожусь в процессе изучения target-c и программирования приложения для iPad.Одной вещью, которую я продолжаю обманывать и перечитывать, является управление памятью.Я добираюсь туда ... медленно.Базовые правила, такие как alloc / retain, должны иметь release.Однако одна относительно простая вещь ускользает от меня, и мне интересно, может кто-нибудь объяснить ...

Возьмите следующий код ...

NSArray *myArray = [[NSArray alloc] init];
myArray = [someNSSet allObjects];

Это относительно прямое кодирование, и для него потребуется[myArray release] утверждение.

Однако я продолжаю видеть примеры (и действительно, я широко использовал следующий «короткий путь» ...

NSArray *myArray = (NSArray *)[someNSSet allObjects];

Как, насколько японять, когда вы используете (NSString *), вам не нужно использовать оператор [myArray release], но я не понимаю, почему.

Может кто-нибудь объяснить это?

Ответы [ 3 ]

2 голосов
/ 26 февраля 2012

Как вы сказали, в первом опубликованном вами коде есть утечка.поэтому вы должны добавить выпуск:

NSArray *myArray = [[NSArray alloc] init];
[myArray release];
myArray = [someNSSet allObjects];

Фактически, когда вы получаете объект с помощью метода, который начинается с alloc, new или copy, вы владеете им, и вы должны выпуститьЭто.Поэтому здесь вы должны освободить массив, полученный с помощью метода alloc.Это соглашение позволяет легко узнать, когда вы владеете объектами, а когда нет.Запомните: alloc, new или copy.

Что касается второго примера, вы получили массив, хотя метод, который не начинается с одного из трех слов (alloc,new или copy), поэтому вы не являетесь владельцем объекта и не несете ответственности за его освобождение.Фактически, полученный вами массив является автоматически выпущенным объектом, что означает, что, хотя его счет сохранения в настоящее время равен 1, он будет автоматически освобожден при сливе чего-либо, называемого пулом автоматического выпуска.1018 * Правила управления памятью .

2 голосов
/ 26 февраля 2012
NSArray *myArray = [[NSArray alloc] init];
myArray = [someNSSet allObjects];

этот код протекает myArray, потому что вы теряете ссылку на NSArray, выделенную в первой строке;вам не нужно alloc здесь, потому что во второй строке вы присваиваете новое значение myArray.

NSArray *myArray = (NSArray *)[someNSSet allObjects];

, и этот пример кода отлично подходит, вы присваиваетерезультат указателя от [someNSSet allObjects] до myArray, и вам не принадлежит возвращаемое значение, поэтому вам не нужно заботиться о его освобождении.

Рассмотрите возможность использования ARC (автоматический счет сохранения) для своего проекта.С ARC компилятор заботится о сохранении счетчиков, поэтому вам не нужно, на самом деле это не разрешено.Существует рефакторинг, который преобразует текущий проект.

1 голос
/ 27 февраля 2012

В первой строке:

NSArray *myArray = [[NSArray alloc] init] 

некоторый объем памяти выделяется для массива (на самом деле в этом случае это бессмысленно, поскольку размер массива равен 0. Имейте в виду, что NSArray является неизменным!).Переменная myArray содержит адрес первого байта зарезервированной области памяти.

Теперь во второй строке вы меняете значение myArray, которое теперь будет указывать на первый байт области памяти, где [someNSSet allObjects]хранится.В этот момент вы больше не знаете, где хранится массив, который вы создали в первой строке.Итак, у вас есть утечка.

Строка:

NSArray *myArray = (NSArray *)[someNSSet allObjects];

верна, так как вы не резервируете никакой памяти на этом этапе.Если вы не используете ARC, вы можете вызвать retain, чтобы GC не попадал в указанный блок памяти.В противном случае вы можете получить BAD_EXEC, когда владелец объекта освободит его, и вы попытаетесь получить к нему доступ, например: [myArray objectAtIndex: 0]

...