Как управлять памятью с изображениями - PullRequest
2 голосов
/ 25 июля 2011

Хорошо, так что, если я написал довольно много кода без выделения объектов, куда идет память?

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

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

, у меня было1006 *

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

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

Ответы [ 3 ]

4 голосов
/ 25 июля 2011
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"];

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

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

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

SomeClass *tempVar = [[SomeClass alloc] initWithSomething:@"Init"];
foo.bar = tempVar;
[tempVar release];
2 голосов
/ 25 июля 2011
imageView.image = [UIImage imageNamed:@"image.png"];

Эта строка является удивительной и правильной.

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

Так "куда идет память?".Он собирается в пул авто-релизов.Но на самом деле, если вы не позвоните alloc, или copy..., или retain, вам не нужно об этом заботиться.

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

1 голос
/ 25 июля 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 возвращает автоматически выпущенный экземпляр этого класса. Вам не нужно отправлять его в своем коде на другую версию, и это вероятный источник сбоя вашей программы.

...