【问题标题】:Weird leaks in UIPickerView methodsUIPickerView 方法中的奇怪泄漏
【发布时间】:2011-11-30 12:36:10
【问题描述】:

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

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

a) 在 vi​​ewWillAppear: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 正在清理,但 Instruments 告诉我 hourString、minuteString 和 self.hours 都被泄露了。真正让我抓狂的是 self.minutes 没有被泄露,而且它的代码格式似乎与 self.hours 相同——我什至复制粘贴后仍然得到相同的泄露/无泄露组合。

如果我能弄清楚这是从哪里来的,我会被诅咒的。有任何想法吗?你们可能需要帮助的任何其他代码?谢谢各位!

编辑:EmptyStack 的建议阻止了self.hoursminuteString 的泄露,但hourString 仍在泄露,现在这段代码中出现了新的泄露,就在@987654328 上面的内容下方@(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 再次泄漏。在我的头爆炸之前我要睡觉了。一夜之间的任何建议都将受到欢迎。

【问题讨论】:

    标签: ios memory-leaks nsstring uipickerview stringwithformat


    【解决方案1】:

    问题在以下几行,

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

    hoursminutes 似乎是 "retained properties",您在分配对象的同时将其分配给属性。例如,在第一行,[NSArray alloc]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;
    

    【讨论】:

    • 嗯,这有帮助 - self.hours 和 minuteString 不再被泄露。然而,hourString 仍然被泄露,并且这个数组现在有一个新的泄露:NSArray *splitStrings = [self.incomingTime componentsSeparatedByString:@":"];
    【解决方案2】:

    好的,终于找到了,对于任何将来偶然发现的人:hour24minute24 没有在 dealloc 中正确释放,所以它到处都在泄漏字符串和数组。我通过注释掉第二次编辑中发布的代码并将其逐行放回直到泄漏出现来找到它。感谢您的建议!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-08
      • 2012-07-06
      • 2011-08-10
      • 1970-01-01
      • 2015-05-09
      • 2015-04-16
      • 2021-03-28
      相关资源
      最近更新 更多