-[CALayer release]: сообщение отправлено освобожденному экземпляру
У меня проблема с некоторым кодом в loadView: метод одного из моих контроллеров представления. По сути, у меня есть представление, которое центрируется в увеличенном виде (на iPad) и имеет несколько ярлыков, кнопок и значков, которые программно загружаются в него.
Проблема возникает, когда контроллер представления вызывает метод dealloc и пытается его освободить. Я получаю -[CALayer release]: сообщение отправлено для освобождения удаленного экземпляра, и приложение падает.
После прочтения об этой ошибке кажется, что я что-то перевыпускаю, но я не думаю, что это так: приведенный ниже код является источником проблем, и я пробовал как авто-релиз, так и вызовы ручного освобождения для всех, а также просто не выпуская их (я знаю, я знаю, это плохо), но это продолжает вызывать хаок.
container = [[UIView alloc] initWithFrame:CGRectNull];
container.autoresizingMask = ( UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin );
container.frame = CGRectMake( (viewSize.width-320)/2, (viewSize.height-480)/2, 320, 480);
[self.view addSubview:container];
UILabel *welcomeTo = [[[UILabel alloc] initWithFrame:CGRectNull] autorelease];
welcomeTo.backgroundColor = [UIColor clearColor];
welcomeTo.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:18.0];
welcomeTo.frame = CGRectMake(23, 15, 103, 24);
welcomeTo.shadowColor = [UIColor blackColor];
welcomeTo.shadowOffset = CGSizeMake( 0, 1 );
welcomeTo.text = @"Welcome to";
welcomeTo.textAlignment = UITextAlignmentLeft;
welcomeTo.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:welcomeTo];
UILabel *progressions = [[[UILabel alloc] initWithFrame:CGRectNull] autorelease];
progressions.backgroundColor = [UIColor clearColor];
progressions.font = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:44.0];
progressions.frame = CGRectMake(20, 30, 280, 56);
progressions.shadowColor = [UIColor blackColor];
progressions.shadowOffset = CGSizeMake( 0, 1 );
progressions.text = @"Progressions";
progressions.textAlignment = UITextAlignmentCenter;
progressions.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:progressions];
UILabel *blurb = [[[UILabel alloc] initWithFrame:CGRectNull] autorelease];
blurb.backgroundColor = [UIColor clearColor];
blurb.font = [UIFont fontWithName:@"HelveticaNeue" size:14.0];
blurb.frame = CGRectMake(23, 100, 274, 51);
blurb.numberOfLines = 3;
blurb.shadowColor = [UIColor blackColor];
blurb.shadowOffset = CGSizeMake( 0, 1 );
blurb.text = @"Kick off the fun by adding some content, or if you're not sure what you're doing, check out the \"Getting Started\" guide!";
blurb.textAlignment = UITextAlignmentLeft;
blurb.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:blurb];
UIButton *button1 = [[UIButton alloc] initWithFrame:CGRectMake(20, 170, 280, 88)];
[button1 setBackgroundImage:[UIImage imageNamed:@"emptyButtonLarge.png"] forState:UIControlStateNormal];
[button1 setBackgroundImage:[UIImage imageNamed:@"emptyButtonLargeHighlighted.png"] forState:UIControlStateHighlighted];
[button1 addTarget:self action:@selector(createChart:) forControlEvents:UIControlEventTouchUpInside];
[container addSubview:button1];
[button1 release];
UIImageView *icon1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"addchart.png"]];
icon1.frame = CGRectMake(30, 180, icon1.frame.size.width, icon1.frame.size.height);
[container addSubview:icon1];
[icon1 release];
UILabel *button1title = [[[UILabel alloc] initWithFrame:CGRectMake(110, 185, 180, 20)] autorelease];
button1title.backgroundColor = [UIColor clearColor];
button1title.font = [UIFont boldSystemFontOfSize:17.0];
button1title.shadowColor = [UIColor blackColor];
button1title.shadowOffset = CGSizeMake( 0, 1 );
button1title.text = @"Create a Chart";
button1title.textAlignment = UITextAlignmentLeft;
button1title.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:button1title];
UILabel *button1blurb = [[[UILabel alloc] initWithFrame:CGRectMake(110, 205, 180, 40)] autorelease];
button1blurb.backgroundColor = [UIColor clearColor];
button1blurb.font = [UIFont systemFontOfSize:13.0];
button1blurb.numberOfLines = 2;
button1blurb.shadowColor = [UIColor blackColor];
button1blurb.shadowOffset = CGSizeMake( 0, 1 );
button1blurb.text = @"A cheat sheet for a displaying a song in any key.";
button1blurb.textAlignment = UITextAlignmentLeft;
button1blurb.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:button1blurb];
UIButton *button2 = [[UIButton alloc] initWithFrame:CGRectMake(20, 270, 280, 88)];
[button2 setBackgroundImage:[UIImage imageNamed:@"emptyButtonLarge.png"] forState:UIControlStateNormal];
[button2 setBackgroundImage:[UIImage imageNamed:@"emptyButtonLargeHighlighted.png"] forState:UIControlStateHighlighted];
[button2 addTarget:self action:@selector(createSet:) forControlEvents:UIControlEventTouchUpInside];
[container addSubview:button2];
[button2 release];
UIImageView *icon2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"addset.png"]];
icon2.frame = CGRectMake(30, 280, icon2.frame.size.width, icon2.frame.size.height);
[container addSubview:icon2];
[icon2 release];
UILabel *button2title = [[[UILabel alloc] initWithFrame:CGRectMake(110, 285, 180, 20)] autorelease];
button2title.backgroundColor = [UIColor clearColor];
button2title.font = [UIFont boldSystemFontOfSize:17.0];
button2title.shadowColor = [UIColor blackColor];
button2title.shadowOffset = CGSizeMake( 0, 1 );
button2title.text = @"Create a Set";
button2title.textAlignment = UITextAlignmentLeft;
button2title.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:button2title];
UILabel *button2blurb = [[[UILabel alloc] initWithFrame:CGRectMake(110, 305, 180, 40)] autorelease];
button2blurb.backgroundColor = [UIColor clearColor];
button2blurb.font = [UIFont systemFontOfSize:13.0];
button2blurb.numberOfLines = 2;
button2blurb.shadowColor = [UIColor blackColor];
button2blurb.shadowOffset = CGSizeMake( 0, 1 );
button2blurb.text = @"A collection of charts that can be displayed like a book.";
button2blurb.textAlignment = UITextAlignmentLeft;
button2blurb.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:button2blurb];
UIButton *button3 = [[UIButton alloc] initWithFrame:CGRectMake(20, 370, 280, 40)];
[button3 setBackgroundImage:[UIImage imageNamed:@"emptyButtonSmall.png"] forState:UIControlStateNormal];
[button3 setBackgroundImage:[UIImage imageNamed:@"emptyButtonSmallHighlighted.png"] forState:UIControlStateHighlighted];
[button3 addTarget:self action:@selector(gettingStarted:) forControlEvents:UIControlEventTouchUpInside];
[container addSubview:button3];
[button3 release];
UILabel *button3title = [[[UILabel alloc] initWithFrame:CGRectMake(20, 370, 280, 36)] autorelease];
button3title.backgroundColor = [UIColor clearColor];
button3title.font = [UIFont boldSystemFontOfSize:17.0];
button3title.shadowColor = [UIColor blackColor];
button3title.shadowOffset = CGSizeMake( 0, 1 );
button3title.text = @"Getting Started";
button3title.textAlignment = UITextAlignmentCenter;
button3title.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:button3title];
UILabel *version = [[[UILabel alloc] initWithFrame:CGRectMake(20, 420, 280, 20)] autorelease];
version.backgroundColor = [UIColor clearColor];
version.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:12.0];
version.shadowColor = [UIColor blackColor];
version.shadowOffset = CGSizeMake( 0, 1 );
version.text = [NSString stringWithFormat:@"Version v%@ (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"], kRevisionNumber];
version.textAlignment = UITextAlignmentCenter;
version.textColor = [UIColor colorWithWhite:1.0 alpha:0.6];
[container addSubview:version];
Свойство контейнера высвобождается в методе dealloc следующим образом:
- (void)dealloc {
[leather release];
[backButton release];
[container release];
[super dealloc];
}
Будем весьма благодарны за любые ответы или предложения, которые могут дать люди. Я действительно в тупик.
3 ответа
Профилируйте ваше приложение в симуляторе с помощью инструмента "Зомби".
Запустите ваше приложение на некоторое время и сделайте все, что вам нужно сделать, чтобы оно вылетело. Когда это произойдет, вы получите всплывающее окно, как на рисунке ниже, и оно остановит профилирование приложения:
Затем, если вы нажмете на маленькую стрелку рядом с адресом (0x158b3c00) .., вы попадете в историю сохранения / освобождения объекта для объекта, который был чрезмерно освобожден (зомби).
Если вы выделите строку выше, где счетчик сохраненных значений равен -1, и откроете View -> Extended detail, она должна указать вам на трассировку стека и строку в вашем коде, где объект был перевыпущен:
Если дважды щелкнуть класс, в котором он находится, он откроет ваш исходный код и покажет вам плохую строку кода:
Чрезмерное высвобождение может происходить во время жизни объектов, а не только при их создании. Несколько советов:
- использовать аксессоры, чтобы указатели были установлены на
nil
- соответствовать вашему использованию
release
/autorelease
, Лично я предпочитаю иметь[[[Class alloc] init] autorelease]
все на 1 линии. - Узнайте разницу между
release
/autorelease
, Давайте построим NSAutoreleasePool - хорошее место для начала.
РЕШЕНО для тех из вас, у кого возникла эта ошибка даже при использовании ARC(которым не нужно вручную «освобождать» переменные)
В моем случае проблема заключалась в том, что внутри объявления моей функции [ строка 1159] я написал, что верну String/NSString, и забыл написать возврат в [ строка 1212] примерно так:
возвращаться @"";
И добавления этого в [ строку 1212] было бы достаточно, чтобы «решить проблему».
PS: Обратите внимание, что эта ошибка времени выполнения возникает (а не ошибка компиляции при создании приложения), потому что в [ строке 1203] я создал/запустил асинхронный блок кода, который в зависимости от того, как я его пишу, может вернуть строку, которая требовалась моя функция (чего я тоже не делал, поэтому и произошла эта ошибка.