user1837078
user1837078

Reputation: 25

ARC - managing memory - views are not released and allocations grow until app crashes

I have been having some memory management issues and random crashes with my app. I have done a lot of work on it to try to clean up the code generally and have converted the project to ARC.

I now have a clear view on the problem - essentially the app does not release views so as a user moves through the app each view is reloaded and retained until finally the app crashes due to memory issues.

I have a UINavigationController. My app runs only in landscape left orientation. When i use

[window setRootViewController:viewController]; 

on load and then

[self.window addSubview:[finalViewController view]]; 

the new view is displayed in portrait - if i rotate it to landscape left with code when i load it in, then all kinds of other random issues come up.

If instead of addSubview i use

[self.viewController.view removeFromSuperview]; 
[self.window setRootViewController:finalViewController];
viewController = nil; 
self.viewController = nil; 
window.viewController = nil;

rotation is ok but views are not released and i have a memory issue with the app and it crashes eventually. Any thoughts would be awesome - appreciate i'm probably missing something fairly basic here. Thanks & happy holidays!

Upvotes: 0

Views: 1029

Answers (1)

PPierson
PPierson

Reputation: 416

How are you loading new views in your app? If you are using a UINavigationController, your AppDelegate should start something like this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    RootViewController* rootController = [[RootViewController alloc] init];
    UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:rootController];
    [self.window setRootViewController:navController];

    [self.window makeKeyAndVisible];

    return YES;
}

To load another view(say from a button press) you will do something like this from within the root view:

SecondViewController *secondView = [SecondViewController alloc] init];
[self.navigationController pushViewController:secondView animated:YES];

This will make the UINavigationController responsible for memory management of your views.

As for rotation, that is handled by giving each of your ViewControllers this method:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft) return YES;
    return NO;
}

Aslong as you are using the UINavigationController the way it is meant to be used, you should not have any non-releasing views. You should read into the UINavigationController: http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html

Another possibility is that the childviews of your view controllers have strong references to their parent view/controller. This will stop a parent viewcontroller from deallocating due to it giving its child a retain count of 1 and the child giving the parent a retain count of 1 as well. Here is a SO post with information on strong & weak references: Objective-C declared @property attributes (nonatomic, copy, strong, weak)

Upvotes: 2

Related Questions