UIPickerView方法中的奇怪泄漏

时间:2011-10-04 09:04:37

标签: ios memory-leaks nsstring uipickerview stringwithformat

构建自定义UIPickerView,我可以让我的用户选择24小时的时间,而无需进入“设置”应用并为整个手机启用24小时制。得到了几个字符串和数组的顽固泄漏,我真的可以使用一些帮助。

我使用字符串创建的数组只有三个位置。小时和分钟都是NSArray合成属性以及ivars。

a)在viewWillAppear:animated中,实际创建了字符串和数组:

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];
    }

c)最后但并非最不重要的是,在dealloc中:

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

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

Analyze即将推出,但是仪器告诉我,HourString,minuteString和self.hours都被泄露了。让我疯狂的是self.minutes没有被泄露,它看起来与self.hours的代码格式相同 - 我甚至复制粘贴,仍然得到相同的泄漏/无泄漏组合。

如果我能弄明白这是来自哪里,我会被诅咒。有任何想法吗?任何进一步的代码你们都可能需要帮忙吗?谢谢,伙计们!

修改:EmptyStack的建议已停止self.hoursminuteString泄露,但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];

编辑2:哦,为了大声喊叫,现在minuteString再次泄漏。在我的脑袋爆炸之前,我要睡觉了。隔夜的任何建议都是最受欢迎的。

2 个答案:

答案 0 :(得分:2)

问题如下:

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

似乎小时分钟 “保留属性” ,并且在分配对象时分配对象属性。例如,在第一行,[NSArray alloc]将{em> retainCount 增加1,而setter self.hours又将retainCount增加1。最后, retainCount 变为2,即使在释放这些对象后也会导致泄漏。在这些情况下,您可以使用便捷构造函数。

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

甚至更简单的方法是直接分配这样的数组,

self.hours = hoursMutable;
self.minutes = minutesMutable;

答案 1 :(得分:1)

好的,终于找到了它,对于将来遇到这种情况的人来说:hour24minute24没有在dealloc中正确发布,所以它在整个地方泄漏了字符串和数组。我发现它是通过评论第二次编辑中发布的代码并将其重新排列,直到泄漏出现。谢谢你的建议!