开发者

How does iOS decide which objects get sent didReceiveMemoryWarning message?

I am working on an iPhone application in which a number of UIViews are dynamically added to and removed from the main UIWindow.

When simulating low memory errors in the simulator, I have discovered that not all view controllers receive the didReceiveMemoryWarning notification. Unfortunately, these are the controllers that would most benefit from implementing this method.

I cannot seem to find good information about where and how the method gets called. I have read mentions that it gets sent to "all UIViewControllers", but this is evidently not the case. Adding a breakpoint in one o开发者_JAVA技巧f the classes that do receive the notification wasn't particularly enlightening either.

This is a complex project but one way these views get added is:

- (void) showMyView
{
  if(!myViewController){
    myViewController = [[MyViewController alloc]init];
    [window addSubview:myViewController.view];
  }
}

MyViewController is a subclass of another class, MySuperViewController, which is itself a subclass of UIViewController. None of those classes have corresponding NIBs; view hierarchies are created programatically.

I am looking for pointers to how I can go about diagnosing the problem.


When you are using .view of the view controller directly, there's a high chance that your view controller won't receive many notifications because it's not the correct way of using view controller. The UIWindow is special case, because the window can automagically know the controller of the view and direct the message to the controller correctly.

However, when you detach your view from UIWindow, the view controller is also detached and not managed by UIWindow any more. I think this is the source of the problem.

I would suggest that you add a navigation controller or tab bar controller as your root view controller, and use that view controller functionality to switch between your child controllers. Note that you should not remove your view controllers when switching so they will be able to receive the messages appropriately.

You might also considering releasing your view controller when not used if initialization of your view controller is trivial and not consuming too much time.


Somewhere in your code you are probably doing something like this:

[[NSNotificationCenter defaultCenter] removeObserver:self];

The only safe place to do this is in -dealloc.

Everywhere else, you should specify the notification that you want to unregister for (this will still potentially break if you register for the same notification as a superlcass).


From the documentation

The default implementation of [didReceiveMemoryWarning] checks to see if the view controller can safely release its view. This is possible if the view itself does not have a superview and can be reloaded either from a nib file or using a custom loadView method.

This method gets called when a Memory Warning "happens"/is simulated. When the memory is low, the system probably posts a notification and a view controller responds to the notification by calling didReceiveMemoryWarning.

If you do not override the method, the default implementation (described above) is called. All view controllers in memory receive the Memory Warning and call this method. They just don't do anything if it is not "safe" to release the view.

In a simple test application with a navigation controller, in both the current view controller and the one previously displayed, didReceiveMemoryWarning is called. I don't know how the NSNotificationCenter works exactly, but it knows who registered for the UIApplicationDidReceiveMemoryWarningNotification. It is probably set up something like this:

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(didReceiveMemoryWarning)
                                             name:UIApplicationDidReceiveMemoryWarningNotification  
                                           object:nil];

For more information, you can look at the Memory Management section in the UIViewController Class Reference.


I entered this question, searching for the right observer dealing with memory warnings. For those using swift, you can register as followed:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "didReceiveMemoryWarning:", name:UIApplicationDidReceiveMemoryWarningNotification, object: nil)

With callback method:

func didReceiveMemoryWarning(notification: NSNotification){
    //Action take on Notification
}

Also, make sure your custom class inherits from NSObject, or you'll be getting this error:

… does not implement methodSignatureForSelector: — trouble ahead
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜