Xcode 4.2.1:使用ARC导致内存泄漏的UIPickerView

时间:2011-12-15 12:58:48

标签: ios memory-leaks uipickerview automatic-ref-counting

对于我最近的一个学校项目,我正在创建一个iPad / iPhone应用程序。几天来,我一直在研究一个内存泄漏的问题。我的应用程序从特定的视图控制器(VCMainStatistics_iPad)开始。从那里,我推送另一个视图控制器(VCSocialMedia_iPad)。之后,我回到第一个视图控制器。

当我重复这个序列时,我注意到(通过使用Instruments - Activity Monitor)应用程序的内存使用量不断增加。通过禁用部分代码,我最终发现它与pickerView有关。此代码没有泄漏:

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

然而,当我增加行数时,泄漏开始出现(每行大约0.07 MB)。显然,这就是为什么我认为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 :(得分:0)

尝试删除-(void)dealloc方法。当您使用ARC时,不应该实现它。如果您不使用ARC,则需要致电[super dealloc]

答案 1 :(得分:0)

从未找到解决方案本身,因此我使用了一种解决方法:通过将NSPickerView替换为NSTableView组件,泄漏不再发生。对于每个注意到这个问题并试图找到解决方案的人:谢谢你的尝试!

答案 2 :(得分:0)

我遇到了类似的问题。它只发生在UIPickerView超出边界时。我修复它的方法是永远不要让UIPickerView移出界限(简单地淡入并淡出以取消隐藏/隐藏UIPickerView)。可能是UIKit中的一个错误。