He Shiming
He Shiming

Reputation: 5819

Correctly handle didReceiveMemoryWarning

One of my UIViewController has several child view controllers. They are built inside the interface builder, by dragging an NSObject to the "Objects" section at left, then put in my own SpecialViewController as "Custom Class". With this setup, upon viewDidLoad I'll have my views and the controller ready. The workflow is suggested by the following screenshot:

Drag "Object" to create instance

And in my implementation, I have:

@interface ParentController : UIViewController
{
     SpecialViewController *svc;
}
@property (nonatomic, retain) IBOutlet SpecialViewController *svc;

As I understand that during didReceiveMemoryWarning I should release my own resources. Then set IBOutlets to nil during viewDidUnload.

I get crashes when simulating low memory in the simulator, with debugger pausing at didReceiveMemoryWarning of SpecialViewController (whose body is just [super didReceiveMemoryWarning];), with error EXC_BAD_ACCESS (code=1, address=0xe0000008). At this time, the parent controller isn't visible, so it can be safely released.

Parent controller also contains only [super didReceiveMemoryWarning]; in didReceiveMemoryWarning. I've tried niling IBOutlets in both classes. It didn't help.

Any idea why this happened?

I'm targeting iOS 4 & 5 with ARC. SpecialViewController is a subclass of UITableViewController.

Through tracing, I found that ParentController didReceiveMemoryWarning is called before SpecialViewController.

Upvotes: 2

Views: 5824

Answers (2)

Ash Furrow
Ash Furrow

Reputation: 12421

Update iOS > 6.0:

Views are no longer purged under low-memory conditions and so this method is never called [1].


View controller's didReceiveMemoryWarning default implementation will release their view; your responsibility is only to release any other views created in viewDidLoad or loadView, as well as any strong references to IBOutlet subviews.

You have a strong reference to another view controller, which will not be recreated when the view becomes visible again. You should not use the didReceiveMemoryWarning to release your the sec instance variable; instead, rely on the SpecialViewController's didReceiveMemoryWarning implementation to take care of releasing it's view.

In practice, I use didReceiveMemoryWarning to release my main view (self.view) and use viewDidUnload to release anything created in viewDidLoad. I find the balance of the names of the methods and their uses intuitive. If you create something in viewDidLoad, release it in viewDidUnload.

Upvotes: 2

Sam
Sam

Reputation: 2579

It seems like you have a view controller with in a view controller here. Is there any particular reason that you have chosen to create the class like this? In my experience each UIViewController should be a separate subclass. Based on the fact that your error arises in didReceiveMemoryWarning, I believe that the issue is elsewhere. Can you share your initialization code for this View Controller?

If you are attempting something like UIViewController Containment, you should probably check out the WWDC topic that covers this process.

Upvotes: 2

Related Questions