Утечки памяти iOS - PullRequest
       26

Утечки памяти iOS

1 голос
/ 21 января 2012

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

Я беру один объект для UIColor в разделе интерфейса и задаю свойство

UIColor *currentColor;
@property (nonatomic, retain) UIColor *currentColor;

После использования этого объекта в разделе реализации я вызываю метод release для этого объекта в dealloc

-(void)dealloc
{
    [currentColor release];
    [super dealloc];
}

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

Ответы [ 3 ]

2 голосов
/ 21 января 2012

Когда вы используете reset setter для свойства currentColor, вы retain этот объект, и если вы retain, copy или alloc память для объекта, вы ДОЛЖНЫ ОТПРАВИТЬ ЕГО.-(void)dealloc лучшее место для этого

2 голосов
/ 21 января 2012

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

Да.

Ради простоты назовите класс, который содержит currentColor объект, как ColorContainer. Теперь, если вы создадите экземпляр ColorContainer, как показано ниже:

ColorContainer* containerColor = [[ColorContainer alloc] init]; // retain count + 1

счет удержания для containerColor становится равным 1.

Предположим, вы создаете экземпляр UIColor и устанавливаете для этого экземпляра свойство currentColor. В этом случае вы можете следовать двумя разными способами. В первом случае вы можете создать экземпляр, подобный следующему. Если вы используете метод экземпляра, такой как initWithRed:green:blue:alpha:, вы должны явно освободить память.

UIColor color* = [[UIColor alloc] initWithRed:0 green:0 blue:0 alpha:1]; // retain count + 1
containerColor.currentColor = color; // retain count +1, the referenced object has a retain count of 2 because you use a retain policy
[color release]; // retain count -1, now  the referenced object has a retain count of 1

Вторым способом вместо этого вы можете использовать метод класса (+ символ). В этом случае вам не нужно освобождать объем памяти, поскольку объект, созданный в этом методе класса, будет автоматически освобожден в определенный момент времени жизни вашего приложения.

containerColor.currentColor = [UIColor whiteColor]; // retain count +1

Теперь предположим, что вы освободили containerColor объект. Если счет сохранения для containerColor равен 1, освобождая его от объекта, который его использует, он позволяет вызвать его метод dealloc и, как следствие, удалить также объект, на который ссылается currentColor.

В этом простом примере вы должны отметить, что объект, на который ссылается currentColor, полностью удаляется из памяти (удаляется), только если он имеет счет сохранения 1. Фактически, если вы сделаете это

UIColor color* = [[UIColor alloc] initWithRed:0 green:0 blue:0 alpha:1]; // retain count + 1
containerColor.currentColor = color; // retain count +1, the referenced object has a retain count of 2
//[color release];

вы создаете утечку памяти (вы понимаете путь?).

Подводя итог, когда вы используете retain, copy, init или new (то же самое, что alloc-init), вы всегда должны вызывать их коллеги release или autorelease.

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

Итак, в качестве метафоры вы можете думать в памяти, как дерево. Предположим, у вас есть родитель (containerColor) и ребенок (currentColor). Если родительский объект (с сохранением количества 1) освобождается, он вызывает его метод dealloc и освобождает память для своего объекта. Если в его методе dealloc вы освобождаете дочерний элемент (с счетом сохранения 1), это вызывает вызов его метода dealloc и свободной памяти. В случае, если количество дочерних элементов превышает один, вы можете вызвать утечку памяти.

Надеюсь, это поможет.

Редактировать

Для получения дополнительной информации вы можете прочитать Об управлении памятью . Начиная с iOS 5 Apple представила ARC. Автоматический подсчет ссылок - это механизм компиляции, который обеспечивает автоматическое управление памятью объектов Objective-C. Для получения информации см. Переход к примечаниям к выпуску ARC .

0 голосов
/ 21 января 2012

Вы должны вызывать release для объекта, только если вы его выделили (через alloc, copy или retain). Свойства с атрибутом retain будут автоматически выполнять управление памятью, если вы правильно их обрабатываете, например, доступ только к ним через self.currentColor. В зависимости от того, как вы создали цветной объект, вы можете или не можете использовать release, но вы всегда должны установить для свойства значение nil в вашем методе dealloc. Два примера:

// If you use this (or some other way to get the color without alloc, copy or retain)
// then you do not need to do any release
self.currentColor = UIColor.blackColor;
self.currentColor = [UIColor colorWithRed:1.0 green:0.5 blue:0.2 alpha:1.0];

// On the other hand if you get it like this, you have to release/autorelease the object
self.currentColor = [[UIColor alloc] initWithRed:1.0 green:0.5 blue:0.2 alpha:1.0];
[self.currentColor release];
// or better
self.currentColor = [[[UIColor alloc] initWithRed:1.0 green:0.5 blue:0.2 alpha:1.0] autorelease];

// dealloc always the same
-(void)dealloc{
    [currentColor release], currentColor = nil;
    [super dealloc];
}

Здесь есть два важных факта:

  1. Для каждого alloc, copy или retain, который выдает ваш код, вы должны ввести release или autorelease.

  2. Всегда используйте self.currentColor для доступа к свойству, а не currentColor, за исключением случаев освобождения. Дело в том, что при использовании self.currentColor система автоматически добавляет код управления памятью. Когда установлен self.currentColor, он автоматически retain с и release с объектами. Только при окончательном освобождении вы должны установить переменную напрямую, для получения дополнительной информации см. этот ответ по теме (спасибо Flex_Addicted).

...