-1

I have a class to enable placeholders for UITextView. This class is called PlaceHolder, and it has initializer that accepts view. It then stores it in strong property and sets itself as view delegate. I store array of PlaceHolders in my strong array in viewDidLoaded:

    self.placeHolders = @[[[PlaceHolder alloc]initWithControl:self.textView andPlaceHolder:@"text"]];

I then call

 -(void)viewWillUnload {
    for(PlaceHolder* holder in self.placeHolders) {
        [holder unload]; // This method does self.view = nil; in each PlaceHolder
    }
    self.placeHolders = nil;
}

Nice. But viewWillUload is deprecated! It says I should use lowMemoryWarning, but it does not means view is unloaded!

So, what is the correct place to remove my placeholders?

user996142
  • 2,753
  • 3
  • 29
  • 48
  • This is the sort of thing that ARC handles for you. If you assign nil to self.placeHolders, all the objects in placeHolders will be released, as will any strong references in these objects. So the question is, is there something special you are doing in unload? –  Aug 16 '15 at 23:07
  • Possible duplicate: http://stackoverflow.com/questions/12536715/ios-6-deprecation-of-viewwillunload-move-to-didreceivememorywarning – musical_coder Aug 16 '15 at 23:12

2 Answers2

1

If you have easily recoverable (i.e. cacheable) large data that you wish to unload when there is low memory, then implement didReceiveMemoryWarning and UIApplicationDidEnterBackgroundNotification to set that data to nil, thus releasing it. Accompany this by "lazy loading", so that if you fetch the data and the data is nil, you reconstruct it. In this way, you are always holding on to the data only if there is no memory pressure (or danger of memory pressure in the background).

You can automate this to some by extent using NSCache, though personally I've never had occasion to do that.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thank you. I was wondering about the case when low memory warning takes place when my view is on the screen. In viewDidUnload I can be sure it was unloaded, but not in memory low warning method. How ever, I found an apple doc, saying I should check self.view.window. Hence, if ! self.view.window I can unload anything – user996142 Aug 17 '15 at 02:56
  • Views are not unloaded any longer. If `self.view.window` is `nil`, your view is not in the interface, which might be because it is presenting another view controller fullscreen and has been temporarily removed from the interface, or because we're in a navigation or tab bar interface and this view controller is not the top / selected view controller. – matt Aug 17 '15 at 03:01
  • I think I should read your book) Thank you. So, should I unload my view? Or will runtime unload whole controller? – user996142 Aug 17 '15 at 03:05
  • I have no idea what you are asking. Views are not unloaded, as I believe I have said more than once. The runtime will release the backing store as needed, thus saving memory, if we are in the background and memory gets tight. But that is no business of yours. Your job is mostly to concern yourself with _data_ (though it is also wise, as we are backgrounded, to strip off any image views holding huge images). – matt Aug 17 '15 at 03:06
0

I finally understood everything, thanks to apple docs and @matt book.

Since iOS 6.0 system never unloads views automatically because new devices have much more RAM. But if I want, I can unload it myself from didReceiveMemoryWarning by nilling by view which then will be created automatically on next access to view due to laziness. But first I need to make sure view is not displayed now. So, correct way is to do the following:

 -(void)didReceiveMemoryWarning  { 
 [super didReceiveMemoryWarning];
 if ([self.view window] == nil) {
    // Low memory and our view is not displayed.
    // We can unload view (if we want), and when controller will be displayed, 
   // system will call self.view, and it will call loadView and then viewdidLoaded
    self.view = nil; // Unload view manually
     // Do any cleanup.
  }
}
user996142
  • 2,753
  • 3
  • 29
  • 48