Xcode 4.2.1: UIPickerView вызывает утечку памяти, используя ARC - PullRequest
4 голосов
/ 15 декабря 2011

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

Когда я повторяю эту последовательность, я замечаю (с помощью Instruments - Activity Monitor), что использование памяти приложением продолжает расти.Отключив части кода, я в конце концов обнаружил, что он как-то связан с 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.Надеюсь, кто-то здесь может помочь: пожалуйста, дайте мне знать, если мне нужно опубликовать больше кода, чтобы прояснить ситуацию.

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

Ответы [ 3 ]

0 голосов
/ 16 апреля 2012

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

0 голосов
/ 10 ноября 2012

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

0 голосов
/ 11 апреля 2012

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

...