For one of my last school projects, I am creating an iPad / iPhone application. For several days I have been working on a problem with a specific memory leak. My application runs on a specific view controller (VCMainStatistics_iPad). From there I click another view controller (VCSocialMedia_iPad). Subsequently, I return to the first view controller.
When I repeat this sequence, I notice (using the tools - Activity Monitor) that the memory usage in the application continues to grow. By disabling parts of the code, I eventually found out that it had something to do with pickerView. This code does not leak:
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return 0; }
However, when I increase the number of rows, leaks begin to occur (approximately 0.07 MB per row). Obviously, this is why I believe pickerView is causing leaks. I tried to remove subviews from pickerView before freeing by setting pickerView to nil and more ... nothing fixes the problem. To hope to make things a little clearer, I'll post some more code.
Header file:
#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 delegate methods:
- (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 Data Collection Methods:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 1; } - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return [lMediaTypes count]; }
Deallocation:
- (void)dealloc { pkSocialMedia = nil; lblGraph = nil; lMediaData = nil; lMediaTypes = nil; }
I just recently converted the project to Objective-C ARC, so there is a good chance this problem has something to do with my lack of experience with the concept. Also, this is also my first Xcode project. Hope someone here can help: please let me know if I need to post more code to clarify the situation.
Thanks in advance!