#ipad #ios4 #nsarray #nsdictionary #uipopovercontroller
#iPad #ios4 #nsarray #nsdictionary #uipopovercontroller
Вопрос:
У меня есть универсальное приложение, часть iPad которого использует UIPopoverController, который отображает UIViewController, совместно используемый с частью iPhone. Когда версия для iPhone загружает и освобождает view controller, все в порядке (утечки памяти нет). Когда версия для iPad загружает ее, происходит утечка двух элементов, NSDictionary и NSArray.
В контроллере представления создаются и освобождаются два объекта таким образом
- (void)setupModels {
fonts = [[NSDictionary alloc] initWithObjectsAndKeys:
@"Baskerville", @"Baskerville",
@"Georgia", @"Georgia",
@"HelveticaNeue", @"Helvetica Neue",
@"Palatino-Roman", @"Palatino Roman",
@"Verdana", @"Verdana", nil];
fontNameKeys = [[NSArray alloc] initWithObjects:
@"Baskerville",
@"Georgia",
@"Helvetica Neue",
@"Palatino Roman",
@"Verdana", nil];
}
- (void)dealloc {
[fonts release], fonts=nil;
[fontNameKeys release], fontNameKeys=nil;
[super dealloc];
}
Версия для iPad создает и отключает UIPopoverController таким образом
- (void)displaySettingsPopover:(id)sender {
if([self.settingsPopover isPopoverVisible]) {
//close the popover view if toolbar button was touched again and popover is already visible
//Thanks to @chrisonhismac
[self.settingsPopover dismissPopoverAnimated:YES];
[self.settingsPopover.delegate popoverControllerDidDismissPopover:self.settingsPopover];
} else {
if (!self.settingsPopover) {
//build our custom popover view
PreferencesViewController_iPhone *pvc = [[PreferencesViewController_iPhone alloc] initWithNibName:nil
bundle:nil
callbackObject:self
selector:@selector(applySettingsFromPopover)];
[pvc.view setBackgroundColor:[UIColor lightGrayColor]];
[pvc.navigationItem setTitle:@"Preferences"];
[pvc setContentSizeForViewInPopover:CGSizeMake(320, 444)];
//create a popover controller
self.settingsPopover = [[UIPopoverController alloc] initWithContentViewController:pvc];
[pvc release];
self.settingsPopover.delegate = self;
}
//present the popover view non-modal with a
//refrence to the toolbar button which was pressed
[self.settingsPopover presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
[self.settingsPopover setDelegate:nil];
[settingsPopover release];
settingsPopover=nil;
}
Я не уверен, почему NSDictionary и NSArray протекают для iPad, но не для iPhone. Профилировщик сообщает, что их количество сохранений изначально равно 1, но никогда не освобождается.
Спасибо!
Комментарии:
1. Кроме того, вы можете захотеть удалить этот ручной вызов делегата. Этого не следует делать.
2. Без этой строки popoverControllerDidDismissPopover: не вызывается, когда пользователь нажимает кнопку панели инструментов, чтобы отменить всплывающее окно. Он вызывается только тогда, когда пользователь щелкает мышью в стороне от всплывающего окна. Возможно, есть лучший способ справиться с этим? Я последовал примеру из другого поста.
Ответ №1:
Эта строка протекает:
self.settingsPopover = [[UIPopoverController alloc] initWithContentViewController:pvc];
если ваше settingsPopover
свойство retain
является copy
или retain
, то это очень вероятно. Дважды проверьте, что, если это действительно так, автоматически запустите его следующим образом:
self.settingsPopover = [[[UIPopoverController alloc] initWithContentViewController:pvc] autorelease];
Комментарии:
1. К сожалению, автоматический выпуск не помог. Когда всплывающее окно отклоняется / освобождается, словарь и массив не освобождаются. Кстати, я добавил NSLog () в dealloc: чтобы убедиться, что он вызывается при выпуске всплывающего окна, и это так. Я подозреваю, что мог бы сделать эти два объекта изменяемыми и также удалить их содержимое в dealloc, но, похоже, это не должно быть необходимым.
2. Кроме того, их определения @property являются (если это полезно)
@property (nonatomic, retain) NSDictionary *fonts; @property (nonatomic, retain) NSArray *fontNameKeys;
3. Я обнаружил немного больше по этой проблеме. Утечку создает не закрытие всплывающего окна, а его открытие. То есть, если я открываю всплывающее окно и оставляю его открытым достаточно долго, чтобы профилировщик создал его снимок, я вижу утечки для словаря и массива.
4. тогда звучит так, как будто вы вызываете
setupModels
более одного раза.