Странные утечки в методах UIPickerView - PullRequest
1 голос
/ 04 октября 2011

Создание пользовательского UIPickerView для того, чтобы я мог позволить своим пользователям выбирать время в 24 часа без необходимости заходить в приложение «Настройки» и включать 24 часа для всего телефона.Получили некоторые утечки из пары строк и массива, и я действительно мог бы использовать некоторую помощь.

Есть только три места, где используются массивы, которые я создаю со строками.часы и минуты являются как NSArray синтезированными свойствами, так и иварами.

a) В viewWillAppear: анимированный, где фактически создаются строки и массивы:

if (TwentyFourHourMode) {
    //set up arrays for 24 hour picker

    NSMutableArray *hoursMutable = [[NSMutableArray alloc] init];
    NSString *hourString;
    for (int i = 0; i < 24; i++) {
        if (i < 10) {
            hourString = [NSString stringWithFormat:@"0%i", i];
        } else {
            hourString = [NSString stringWithFormat:@"%i", i];
        }
        [hoursMutable addObject:hourString];
    }
    self.hours = [[NSArray alloc] initWithArray:hoursMutable];
    [hoursMutable release];

    NSMutableArray *minutesMutable = [[NSMutableArray alloc] init];
    NSString *minuteString;
    for (int i = 0; i < 60; i++) {
        if (i < 10) {
            minuteString = [NSString stringWithFormat:@"0%i", i];
        } else {
            minuteString= [NSString stringWithFormat:@"%i", i];
        }
        [minutesMutable addObject:minuteString];
    }
    self.minutes = [[NSArray alloc] initWithArray:minutesMutable];
    [minutesMutable release];
    //more stuff which does not leak or reference the arrays/strings in question
} else {
    //unrelated crap
}

b) в моих методах делегатов UIPickerView - все, что использует эти два массива:

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

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    if (component == 0) {
        return self.hours.count;
    } else if (component == 1) {
        return self.minutes.count;
    } else {
        return 0;
    }    
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if (component == 0) {
        return [self.hours objectAtIndex:row];
    } else if (component == 1) {
        return [self.minutes objectAtIndex:row];
    } else {
        return nil;
    }
}

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
    switch(component) {
        case 0: return 44;
        case 1: return 50;
        default: return 44;
    }

}

- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    if (component == 0) {
        [hour24 release];
        hour24 = [self.hours objectAtIndex:row];
        [hour24 retain];
    } else if (component == 1) {
        [minute24 release];
        minute24 = [self.minutes objectAtIndex:row];
        [minute24 retain];
    }

в) и, наконец, что не менее важно, в dealloc:

//set arrays to nil
self.hours = nil;
self.minutes = nil;

//release arrays
[hours release];
[minutes release];

Анализ идет полным ходом, но Instruments сообщает мне, что hourString, minuteString и self.hours просочились.Что меня действительно сводит с ума, так это то, что self.minutes не пропускается, и кажется, что это тот же формат кода, что и self.hours - я даже вставляю его в копию и все равно получаю ту же комбинацию «утечка / отсутствие утечки».

Будь я проклят, если смогу понять, откуда это исходит.Есть идеи?Любой дополнительный код вам может понадобиться?Спасибо, ребята!

Редактировать : предложение EmptyStack остановило утечку self.hours и minuteString, но hourString все еще протекает, и теперь в этом коде есть новая утечка чуть нижевышеприведенный материал в viewWillAppear:animated (self.incomingTime - это синтезированное свойство NSString, все массивы здесь инициализируются локально):

NSArray *splitStrings = [self.incomingTime componentsSeparatedByString:@":"];
NSString *hourToDisplay = [splitStrings objectAtIndex:0];
//set this here so it doesn't give a null value
hour24 = [[NSString alloc] initWithString:hourToDisplay];
NSString *minuteSplitter = [splitStrings objectAtIndex:1];
NSArray *splitMinutes = [minuteSplitter componentsSeparatedByString:@" "]; 
NSString *minuteToDisplay = [splitMinutes objectAtIndex:0];
minute24 = [[NSString alloc] initWithString:minuteToDisplay];

Edit 2: Oh, для вызовагромко, теперь minuteString снова подтекает.Я иду спать, прежде чем моя голова взорвется.Любые предложения в одночасье будут приветствоваться.

Ответы [ 2 ]

2 голосов
/ 04 октября 2011

Проблемы в следующих строках,

self.hours = [[NSArray alloc] initWithArray:hoursMutable];
self.minutes = [[NSArray alloc] initWithArray:minutesMutable];

Кажется, часы и минуты являются «сохраненными свойствами» , и вы выделяете объекты при назначении его свойствам. Например, в первой строке [NSArray alloc] увеличивает retainCount на 1, а установщик self.hours в свою очередь увеличивает retainCount на 1. Наконец, retainCount становится 2, что вызывает утечку даже после того, как вы отпустите эти объекты. В этих случаях вы можете использовать удобные конструкторы.

self.hours = [NSArray arrayWithArray:hoursMutable];
self.minutes = [NSArray arrayWithArray:minutesMutable];

И даже более простой способ - напрямую назначать эти массивы, как этот,

self.hours = hoursMutable;
self.minutes = minutesMutable;
1 голос
/ 05 октября 2011

Ладно, наконец-то нашёл это, для любого, кто столкнется с этим в будущем: hour24 и minute24 не были должным образом освобождены в dealloc, так что это повсеместно пропускало строки и массивы. Я нашел его, закомментировав код, опубликованный во 2-й редакции, и поместив его обратно построчно, пока не возникла утечка. Спасибо за предложения!

...