Как управлять памятью с изображениями

Итак, если я написал довольно много кода, не выделяя никаких объектов, куда денется память?

Например, вместо того, чтобы иметь

UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];

я имел

imageView.image = [UIImage imageNamed:@"image.png"];

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


person user813031    schedule 25.07.2011    source источник


Ответы (3)


UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];

Вы сделали двойной релиз. [UIImage imageNamed] освобождается автоматически, поэтому вам не нужно явно освобождать объект. Вероятно, ваше приложение вылетело из-за двойных выпусков, а не из-за невыпущенных объектов.

Прочтите простое практическое правило: путаница выпуска / автоматического выпуска в какао для iphone:

Правило простое: если вы выделяете, копируете или сохраняете, вы обязаны освободить. Если вы этого не сделали, это не так. Однако, если вам нужно полагаться на то, что объект остается поблизости, вы должны сохранить (и впоследствии освободить).


Еще примеры:

imageView.image = [UIImage imageNamed:@"image.png"];

Приведенный выше код действителен, вам не нужно его выпускать. Но если вы используете много прямых назначений с невыпущенными объектами, такими как этот:

foo.bar = [[SomeClass alloc] initWithSomething:@"Init"];

Вы можете легко исправить их, добавив автозапуск:

foo.bar = [[SomeClass alloc] initWithSomething:@"Init"] autorelease];

Или, если вам нужен длинный, но, возможно, более подходящий способ (поскольку вы контролируете, когда объект освобождается):

SomeClass *tempVar = [[SomeClass alloc] initWithSomething:@"Init"];
foo.bar = tempVar;
[tempVar release];
person Manny    schedule 25.07.2011

imageView.image = [UIImage imageNamed:@"image.png"];

Эта строчка классная и правильная.

в реализации метода imageNamed: он может выделить память для нового UIImage, создать экземпляр нового UIImage в этой памяти, а затем autorelease перед его возвратом. Пул автозапуска истощается после запуска вашего кода, освобождая объект изображения, если его ничто не сохранило.

Итак, «куда девается память?». Он попадает в пул автозапуска. Но на самом деле, если вы не позвоните alloc, copy... или retain, вам не о чем беспокоиться.

Как замечает Мэнни, ваш первый фрагмент не соответствует действительности и является неверным.

person Alex Wayne    schedule 25.07.2011

Вы путаете объявление переменных с выделением памяти / объектов. Важная часть вашего кода в обоих приведенных выше случаях на самом деле такова:

[UIImage imageNamed:@"image.png"];

Этот код вызывает метод class класса UIImage, который выполняет ряд функций. Одна из этих вещей - выделение и инициализация объекта UIImage. В вашем первом примере вы сохранили этот выделенный объект в переменной с именем myImage. Затем вы переместили свой новый блестящий объект в другую переменную (класса), `imageView.image '.

UIImage *myImage = ...

Во втором примере, который вы дали, вы по-прежнему сохраняете этот выделенный объект в переменной, за исключением того, что в этом случае вы пропустили промежуточное присвоение и сохранили объект непосредственно в переменной класса imageView.image.

imageView.image = [UIImage imageNamed:@"image.png"];

Один из способов сравнить переменные с объектами - это сравнить их с домами. В этом сценарии переменная - это ваш адрес, а объект - ваш дом. Ваш адрес может быть у нескольких человек, но независимо от того, сколько их, когда они решат посетить, они собираются в один и тот же дом. Итак, в ваших примерах myImage и imageView.image - это адреса, указывающие на один и тот же дом или объект, экземпляр UIImage. В вашем примере вам действительно не нужно создавать промежуточную переменную, если вы не используете ее для какой-либо другой цели.

Что касается сбоев, вам следует ознакомиться с Руководство Apple по управлению памятью. Это может занять некоторое время, но вы привыкнете к стандартам, которым следует Apple в отношении сохранения и освобождения объектов. Обратите внимание, что новый автоматический подсчет ссылок в XCode 4.2 решает многие из этих проблем, но также требует собственного обучения. Но в итоге вы получаете сбои из-за того, что выпускаете объект, которым не владеете. Метод класса imageNamed в UIImage возвращает автоматически выпущенный экземпляр этого класса. Вам не нужно отправлять ему еще одну версию в своем коде, и это вероятный источник сбоя вашей программы.

person Perception    schedule 25.07.2011