Большой счетчик удержаний для недавно созданного объекта. Цель-C

Я получаю странный случай чрезмерного количества удержаний для контроллера представления, который я загружаю при нажатии кнопки.

Это код:

-(IBAction)new
{
    if (!viewSpace)
        viewSpace = [[ViewSpace alloc] initWithNibName:@"ViewSpace" bundle:nil];

    viewSpace.delegate = self;

    viewSpace.view.frame = CGRectMake(0, 0, viewSpace.view.frame.size.width, viewSpace.view.frame.size.height);

    [self presentModalViewController:viewSpace animated:YES];

    NSLog(@"Count Retain: %d",[viewSpace retainCount]);

}
-(void)viewSpaceWasDissmissed:(id)sender
{
    [self dismissModalViewControllerAnimated:YES];
    [viewSpace release];    
    NSLog(@"Count Retain: %d",[viewSpace retainCount]);
}

Когда IBAction New выполняется в первый раз, счетчик удержания равен 5, когда только что создается. (Должно быть 1).

Когда объект ViewSpace должен быть выгружен, вызывает функцию viewSpaceWasDismissed, чтобы удалить модальное представление и освободить предыдущий объект.

Проблема в том, что счетчик сохраненных данных никогда не достигает 0, а метод dealloc ViewSpace никогда не вызывается, вызывая утечки памяти.

Мой вопрос: как возможно, что недавно созданный ViewController имел 5 сохранений? Я убедился, что это никогда не создавалось раньше.

Спасибо.


person NemeSys    schedule 25.01.2012    source источник
comment
retainCount совершенно бесполезен. Вы тратите время на размышления об этом.   -  person bbum    schedule 25.01.2012
comment
Да, но проблема в том, что освобождение объекта ViewSpace никогда не достигается. Это приводит к чрезмерному использованию памяти в моем приложении и сбоям.   -  person NemeSys    schedule 25.01.2012
comment
@bbum ты смотришь RSS-канал для тега keepCount, что ли? ;)   -  person Abizern    schedule 25.01.2012
comment
@ user1132003 Затем вам нужно выяснить, откуда берутся дополнительные удержания, о чем retainCount вам не скажет. Используйте инструмент Allocations и включите отслеживание событий сохранения. Затем посмотрите на все события сохранения и выясните, какое из них не сбалансировано release.   -  person bbum    schedule 26.01.2012
comment
@abizem Да, это немного развлекает. Я полностью признаю, что меня легко забавляют.   -  person bbum    schedule 26.01.2012


Ответы (4)


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

В более общем смысле метод -retainCount бесполезен по подобным причинам, и вы никогда не должны его вызывать. Это вам не поможет и запутает.

Для отладки вашей утечки я предлагаю использовать Leaks Instrument, осматривая объект и анализируя, откуда происходит каждое удержание и выпуск, чтобы определить, являются ли какие-либо неправильными.

person Catfish_Man    schedule 25.01.2012

Проверьте документацию для -retainCount. Я считаю, что это говорит о том, что вы не должны называть это самостоятельно - вам просто нужно позаботиться о любых удержаниях, которые вы вызываете, и не беспокоиться о «фактическом» счетчике удержаний.

person Daniel    schedule 25.01.2012

Вы делаете здесь две ошибки:

  1. Контроллер текущего представления сохраняет модально представленный контроллер представления и освобождает его при закрытии. Таким образом, вы должны выпустить viewSpace после того, как он будет представлен, и вам не нужно сообщение о выпуске в dismissModalViewController методе. Кстати, ViewSpace - плохое имя для контроллера представления. Мне пришлось прочитать строку, в которой вы представляете его как контроллер представления, прежде чем я узнал, что это контроллер представления. Я думаю, что ViewSpaceController - более информативное имя.
  2. Вы используете retainCount, что всегда плохая идея. Все, что имеет значение, это то, что в вашем new методе вы создали принадлежащий объекту (с alloc) и уравновесили это владение выпуском (или, по крайней мере, вы сделаете это, когда внесете исправление, которое я предложил в пункте 1). Вот и все. Вы получили право собственности на объект и освободили его. Метод retainCount не сообщает вам абсолютно ничего, что могло бы быть вам полезно. Не делай этого. Просто сбалансируйте владение и выпуск, и это все, что имеет значение.
person Abizern    schedule 25.01.2012
comment
Я подал заявку, как было предложено. Но проблема все еще остается. метод dealloc никогда не достигается, и у меня проблемы с использованием памяти. - person NemeSys; 25.01.2012
comment
retainCount не поможет вам найти утечку. Запустите приложение через инструменты и посмотрите, что на самом деле происходит с вашим контроллером представления. - person Abizern; 25.01.2012
comment
Я сделал, я удалил счетчик остатков, и я использую инструменты. Проблема в том, что каждый раз, когда объект ViewSpace загружается и выгружается, объем памяти увеличивается на 1,30 Мбайт. После нескольких действий открытия / закрытия приложение вылетает. - person NemeSys; 26.01.2012
comment
Если для очистки объекта используется метод dealloc, и метод dealloc вызывается автоматически, когда счетчик сохраненных данных достигает нуля, почему я должен вызывать release в том же методе, в котором он был создан, а не в другом методе? Этот объект должен быть активен, пока пользователь не закроет объект ViewSpace? - person NemeSys; 26.01.2012
comment
Вам нужно освободить его, потому что он сохраняется текущим контроллером представления, когда он представлен, и текущий контроллер представления также освободил его, когда он был отклонен. Вот почему вам нужно сбалансировать выделение памяти с помощью init в той же функции, что я объяснил в пункте 1). - person Abizern; 26.01.2012
comment
Хорошо, тогда, насколько я понимаю, проблема в том, что родительский элемент ViewSpace никогда не удаляется, потому что это окно главного меню. Как лучше всего освободить всю память, используемую ViewSpace во время выполнения? Спасибо за каждый ответ :) - person NemeSys; 26.01.2012

Я не уверен на 100% во всех подсчетах, но вот некоторые из них:

  • Создание экземпляров - 1
  • СИБ - 1+
  • Сильные свойства (1+)

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

person lukecampbell    schedule 25.01.2012
comment
ARC не применяется к этому коду. Вызовы release и retainCount не разрешены в ARC. - person Abizern; 25.01.2012