NSDateFormatter memory leak?

别等时光非礼了梦想. 提交于 2019-12-12 02:16:51

问题


I have a problem with NSDateFormatter dateFromString: method. There is an array of dictionaries with string dates and I want to convert them to NSDates. But there is a huge heap growth every time I call this method (I need to call it more than once, cause it's an "update" method). Also I call it in background thread and ARC is on. What am I doing wrong? Any help, please.

UPDATE: Full code of the function:

- (GraphController *) initGraphWithData: (NSArray *) points forInterval: (GraphInterval) interval andFrame: (CGRect) frame gestures: (BOOL) gestures secondGraph: (NSArray *) secondPoints graphNames: (NSArray *) graphNames

{
self = [super init];

_calendar = [NSCalendar currentCalendar];

_secondPoints = secondPoints;
_graphNames = graphNames;

[self.view setFrame:frame];

_points = [[NSMutableArray alloc] init];
double minValue = HUGE_VALF, maxValue = -HUGE_VALF;
NSDate *minDate = [NSDate date], *maxDate = [NSDate dateWithTimeIntervalSince1970:0];
NSMutableDictionary *datesTable = [[NSMutableDictionary alloc] init];          


int index = 0;
for(NSArray *pointArray in points){

    NSDictionary *point = pointArray[0];
    NSMutableDictionary *newPoint = [[NSMutableDictionary alloc] initWithDictionary:point];


    // convert date        
    NSString *dateString = (NSString *)[point objectForKey:@"date"];
    NSLog(@"dateString to convert: %@", dateString);
    [_dateFormatter setDateFormat:@"MM/dd/yyyy"];
    NSDate *date = [_dateFormatter dateFromString: dateString];
    [newPoint setObject: date forKey:@"date"];


    // convert numbers
    [newPoint setObject: [NSNumber numberWithFloat:[((NSString *)[point objectForKey:@"value"]) floatValue]] forKey:@"value"];
    if(secondPoints)
        [newPoint setObject: [NSNumber numberWithFloat:[((NSString *)[secondPoints[index] objectForKey:@"value"]) floatValue]] forKey:@"secondValue"];
    [newPoint setObject: [NSNumber numberWithInt:index]  forKey:@"index"];

    // min and max
    if([[newPoint objectForKey:@"value"] floatValue] < minValue)
        minValue = [[newPoint objectForKey:@"value"] floatValue];
    if([[newPoint objectForKey:@"value"] floatValue] > maxValue)
        maxValue = [[newPoint objectForKey:@"value"] floatValue];

    // check second value
    if(self.secondPoints){            
        if([[newPoint objectForKey:@"secondValue"] floatValue] < minValue)
            minValue = [[newPoint objectForKey:@"secondValue"] floatValue];
        if([[newPoint objectForKey:@"secondValue"] floatValue] > maxValue)
            maxValue = [[newPoint objectForKey:@"secondValue"] floatValue];
    }

    if([[newPoint objectForKey:@"date"] timeIntervalSince1970] > [maxDate timeIntervalSince1970])
        maxDate = [newPoint objectForKey:@"date"];
    if([[newPoint objectForKey:@"date"] timeIntervalSince1970] < [minDate timeIntervalSince1970])
        minDate = [newPoint objectForKey:@"date"];

    [self.points addObject:newPoint];
    [datesTable setObject:newPoint  forKey: [[NSNumber numberWithDouble:[date timeIntervalSince1970]] stringValue] ];

    index++;            

}




// set draw parameters

_drawVars = [[NSMutableDictionary alloc] init];

NSDate *startSearchDate;
switch (interval) {
    case GraphIntervalWeek:
        startSearchDate = [maxDate dateByAddingTimeInterval:-7*24*3600];
        break;
    case GraphIntervalMonth:
        startSearchDate = [maxDate dateByAddingTimeInterval: -31*24*3600];
        break;
    case GraphIntervalSixMonths:
        startSearchDate = [maxDate dateByAddingTimeInterval:-6*31*24*3600];
        break;
    case GraphIntervalYear:
        startSearchDate = [maxDate dateByAddingTimeInterval:-365*24*3600];
        break;
    case GraphIntervalAllTime:
        break;
    default:
        break;
}

NSMutableDictionary *searchPoint;

while(searchPoint == nil && [startSearchDate timeIntervalSince1970] > [minDate timeIntervalSince1970]){
    searchPoint = [datesTable objectForKey:[[NSNumber numberWithDouble:[startSearchDate timeIntervalSince1970]] stringValue]];
    startSearchDate = [startSearchDate dateByAddingTimeInterval:-24*3600];
}

if(searchPoint != nil && interval != GraphIntervalAllTime)
 [self.drawVars setObject:[searchPoint objectForKey:@"index"] forKey:@"startDrawIndex"];
else
 [self.drawVars setObject:[NSNumber numberWithInt:0] forKey:@"startDrawIndex"];

[self.drawVars setObject:[[NSNumber numberWithFloat:minValue] copy] forKey:@"minValue"];
[self.drawVars setObject:[[NSNumber numberWithFloat:maxValue] copy] forKey:@"maxValue"];
[self.drawVars setObject:minDate forKey:@"minDate"];
[self.drawVars setObject:maxDate forKey:@"maxDate"];
[self.drawVars setObject:datesTable forKey:@"datesTable"];



// set drawImageView
_drawArea = [[UIImageView alloc] initWithFrame: frame];
[self.view addSubview:self.drawArea];


// set overlayImageView for fingerInpect
_inspectOverlay = [[UIImageView alloc] initWithFrame:frame];
[self.view addSubview:self.inspectOverlay];

// set hintUIView for fingerInspect
_hint = [[Hint alloc] initWithFrame:frame];
[self.hint initHint];
self.hint.hidden = YES;
[self.drawArea addSubview:self.hint];    



UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandler:)];
UILongPressGestureRecognizer *longPressRecognizer  = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressHandler:)];    


if(gestures)
    [self.view addGestureRecognizer:panRecognizer];
[self.view addGestureRecognizer:longPressRecognizer];

return self;
}

回答1:


I see you are using Heapshot analysis. Good. Here are some more details:

http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/

Now, hopefully, each one of your Heapshot iterations represents doing something in your app that should return it back to the base state. Opening and closing a document, for example.

If that is the case, your data is showing a 500K-600K growth per iteration. That is quite a bit.

Note that trying to analyze the last iteration is generally useless; many of those objects will exist because of whatever the current state of the app is. You really want to focus on that 2nd or 4th iteration.

As for why that specific date or date formatter is leaking, turn on reference count event tracking and then review the retain/release events for one of the leaked objects. There will be some number of extra retains.




回答2:


Something you are doing right is init the NSDateFormatter before entering the loop. If you are expecting the same date format (MM/dd/yyyy) you can put in the same place you init it as well. It can be that you are allocating too many objects, so I could advise putting everything inside an @autoreleasepool {} (aka: the content of the loop inside the autorelease).

I am seeing you are allocating the *newPoint inside the for and then you are setting the date to that object. What do you do after?



来源:https://stackoverflow.com/questions/17765342/nsdateformatter-memory-leak

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!