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

#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 более одного раза.