Xcode 4.2.1: UIPickerView вызывает утечку памяти с использованием ARC

Для одного из моих последних школьных проектов я создаю приложение для iPad/iPhone. Уже несколько дней я работаю над проблемой с определенной утечкой памяти. Мое приложение запускается на определенном контроллере представления (VCMainStatistics_iPad). Оттуда я нажимаю другой контроллер представления (VCSocialMedia_iPad). После этого я возвращаюсь к первому контроллеру представления.

Когда я повторяю эту последовательность, я замечаю (используя Инструменты - Монитор активности), что использование памяти приложением продолжает увеличиваться. Отключив части кода, я в конце концов обнаружил, что это как-то связано с pickerView. Этот код не дает утечек:

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return 0;
}

Однако, когда я увеличиваю количество строк, начинают появляться утечки (примерно 0,07 МБ на строку). Очевидно, именно поэтому я считаю, что pickerView является причиной утечек. Я пытался удалить подвиды из pickerView перед освобождением, установив для pickerView значение nil и многое другое... ничто не решает проблему. Чтобы, надеюсь, немного прояснить ситуацию, я опубликую еще немного кода.

Заголовочный файл:

#import "UniversalViewController.h"

#define DATATYPE_SOCIALMEDIA 0

@interface VCSocialMedia_iPad : UniversalViewController <UIPickerViewDataSource, UIPickerViewDelegate>
{
    NSArray *lMediaTypes;
    NSMutableArray *lMediaData;

    __weak IBOutlet UIPickerView *pkSocialMedia;
    __weak IBOutlet UILabel *lblGraph;
}

@end

Методы делегата PickerView:

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    // Get key of requested row
    NSString *title = [[lMediaTypes objectAtIndex:row] capitalizedString];

    // Capitalize first letter
    title = [title capitalizedString];

    // Return
    return title;
}



- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    // Make or clear data lists
    if( lGraphDayDataX[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] == nil ){
        lGraphDayDataX[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] = [[NSMutableArray alloc] init];
    }
    else{
        [lGraphDayDataX[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] removeAllObjects];
    }

    if( lGraphDayDataY[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] == nil ){
        lGraphDayDataY[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] = [[NSMutableArray alloc] init];
    }
    else{
        [lGraphDayDataY[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] removeAllObjects];
    }

    // Get required key
    NSString *dictKey = [lMediaTypes objectAtIndex:row];

    if( [dictKey isEqualToString:@"total_views"] ){
        return;
    }

    // Adjust graph label
    lblGraph.text = [NSString stringWithFormat:@"Stats from %@", dictKey];

    // Get data of selected row
    NSArray *mediaData = [lMediaData objectAtIndex:row];

    // Add each day to data lists: inversed order
    for( int day = [mediaData count]-1; day >= 0; day-- ){
        NSDictionary *dayData = [mediaData objectAtIndex:day];
        dictKey = @"wpsd_trends_date";

        NSString *date = [dayData objectForKey:dictKey];
        // Remove 00:00:00
        date = [date stringByReplacingOccurrencesOfString:@" 00:00:00" withString:@""];
        [lGraphDayDataX[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] addObject:date];

        dictKey = @"wpsd_trends_stats";
        NSString *stats = [dayData objectForKey:dictKey];
        [lGraphDayDataY[iSelectedServerIndex][DATATYPE_SOCIALMEDIA] addObject:stats];
    }

    // Update the graphs
    [self updateGlobalScreen];
}

Методы источника данных PickerView:

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;
}



- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return [lMediaTypes count];
}

Освобождение:

- (void)dealloc
{
    pkSocialMedia = nil;
    lblGraph = nil;

    lMediaData = nil;
    lMediaTypes = nil;
}

Я только недавно преобразовал проект в Objective-C ARC, поэтому есть большая вероятность, что эта проблема как-то связана с отсутствием у меня опыта работы с этой концепцией. Кроме того, это также мой первый проект Xcode. Надеюсь, кто-то здесь может помочь: пожалуйста, дайте мне знать, если мне нужно опубликовать больше кода, чтобы прояснить ситуацию.

Заранее спасибо!


person Tybs    schedule 15.12.2011    source источник


Ответы (3)


Попробуйте удалить метод -(void)dealloc. Это не должно быть реализовано, когда вы используете ARC. Если вы не используете ARC, ему нужно вызвать [super dealloc].

person Josh Brown    schedule 11.04.2012
comment
Проект уже закончен: вместо него я использовал компонент NSTableView, который устранил утечку. У меня больше нет доступа к файлам, поэтому больше нет возможности попробовать ваше решение. Тем не менее, спасибо за предложение! - person Tybs; 16.04.2012

Самого решения так и не нашел, поэтому использовал обходной путь: заменив NSPickerView компонентом NSTableView, утечка больше не происходила. Всем, кто заметил проблему и пытался найти решение: спасибо за попытку!

person Tybs    schedule 16.04.2012

У меня похожая проблема. Это происходит только тогда, когда UIPickerView выходит за пределы. Я исправил это таким образом, чтобы UIPickerView никогда не выходил за пределы (просто исчезал и исчезал, чтобы отобразить/скрыть UIPickerView). Вероятно, ошибка в UIKit.

person ninjaneer    schedule 10.11.2012