1

We are creating an application with a main menu from which you can navigate to a second view with a back button and about 6 other buttons which loads 6 different subviews into memory (array) depending which one you selected.

When the user selects the 'back' button I want to erase anything from memory that was allocated in the screen with the 6 buttons.

At the moment the application just builds up memory and nothing seems to get deallocated. Please see the screenshot in the URL below:

http://oi41.tinypic.com/jfi8ma.jpg

 //Load all tab views into memory before loading them into an array
TimeViewController *timeView = [[TimeViewController alloc]init];
LocationViewController *locationView = [[LocationViewController alloc]init];
DropOffViewController *dropOffView = [[DropOffViewController alloc]init];
CompanyViewController *companyView = [[CompanyViewController alloc]init];
PaymentViewController *paymentView = [[PaymentViewController alloc]init];

//Set delegates of the tab views
timeView .delegate = self;
locationView.delegate = self;

//Load all tab views into array
[tabViews insertObject:timeView atIndex:0];
[tabViews insertObject:locationView atIndex:1];
[tabViews insertObject:dropOffView atIndex:2];
[tabViews insertObject:companyView atIndex:3];
[tabViews insertObject:paymentView atIndex:4];

for(int x = 0; x<5;x++)
{
    UIViewController *tempView = [[UIViewController alloc]init];
    tempView = [tabViews objectAtIndex:x];
    
    [self addChildViewController:tempView];
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
JakesRassie
  • 616
  • 1
  • 6
  • 20
  • did you declare your delegates as weak properties? – Kreiri Jun 25 '13 at 06:30
  • No, if I set my delegates as weak properties I get the following error: error: "existing instance variable '_delegate' for __weak property 'delegate' must be __weak" – JakesRassie Jun 25 '13 at 06:33
  • If your delegates are retained, then you have [retain cycle](http://stackoverflow.com/questions/791322/retain-cycles-why-is-that-such-a-bad-thing). – Kreiri Jun 25 '13 at 06:36
  • Thanks, do you have any idea how I could avoid cycles in my project? I presume this has to do with the way I load object into memory in view controller B? – JakesRassie Jun 25 '13 at 06:44
  • Don't retain delegates, for example. – Kreiri Jun 25 '13 at 06:46
  • To not retain objects I should probably release them when I'm done with them. But I can't release objects/properties while using ARC so how do you not retain them? – JakesRassie Jun 25 '13 at 06:50
  • I declare my delegate properties like this: @property (nonatomic, strong) id delegate; So I actually don't use the work retain anywhere. – JakesRassie Jun 25 '13 at 06:52
  • Keywords [`strong` and `retain` are synonyms](http://stackoverflow.com/questions/8927727/objective-c-arc-strong-vs-retain-and-weak-vs-assign). To retain an object means to create a strong reference to that object. – Kreiri Jun 25 '13 at 06:59
  • So from what I've read the Strong keywork retains the object, but if I set the delegate property to this for example: @property (nonatomic, unsafe_unretained) id delegate; I get an error:error: existing instance variable '_delegate' for property 'delegate' with unsafe_unretained attribute must be __unsafe_unretained – JakesRassie Jun 25 '13 at 07:10
  • @JakesRassie Then don't explicitly declare the backing variables... – borrrden Jun 25 '13 at 08:16

2 Answers2

5

You created a retain cycle.

You declared your delegates as strong properties. It means that when you do

timeView .delegate = self;

timeView retains self.

When you add timeView as child view controller to self, self retains timeView.

If self holds strong reference to tabViews, then it's an owner of tabViews, which is an owner of objects added to it, which makes another retain cycle: self owns tabViews which owns timeView which owns self.

If you don't want retain cycles, your child objects must never hold strong references to their parents or any of their parents' parents. Never declare delegates as strong properties.

As for your "must be __weak" error, please see this answer.

Community
  • 1
  • 1
Kreiri
  • 7,840
  • 5
  • 30
  • 36
  • Thanks I have set all my delegates to weak now but its still getting retained somewhere. Do you have any idea where this could be? Thanks for your help so far. – JakesRassie Jun 25 '13 at 07:40
  • How would I know? It's a common mistake with delegates, but it's not the only way to create a retain cycle. – Kreiri Jun 25 '13 at 07:56
  • Here's another screenshot of my memory profile of what takes up the most memory, maybe this could help identify the problem: http://oi39.tinypic.com/2iligbo.jpg – JakesRassie Jun 25 '13 at 08:23
0

Try with this code to erase your memory on back button action

for(UIView *view in self.view.subviews)
{
    [view removeFromSuperView];
    view=nil;
}   
Rox
  • 909
  • 11
  • 31
  • Setting something to nil does *not* force deallocation, it just looks nice. – CodaFi Jun 25 '13 at 06:46
  • But i think when you remove the view, it deallocate the memory. – Rox Jun 25 '13 at 06:55
  • Not if something else is retaining them, like the array he showed in his sample code. – CodaFi Jun 25 '13 at 06:57
  • If we deallocate the array also then?? – Rox Jun 25 '13 at 07:05
  • I have tried setting the array to nil which didn't do anything for me, I have a Datepicker component in one of my subviews which is what takes up most of the memory so I know the subview is still in memory even after I set my array to nil. – JakesRassie Jun 25 '13 at 07:12
  • Rox, If I try your for loop the size in memory actually doubles, do you have any idea why? I had to remove the view=nil; because I recieved an error stating that fast enumeration can't be modified in ARC – JakesRassie Jun 25 '13 at 07:37
  • The loop which you provided me runs 9 times. – JakesRassie Jun 25 '13 at 08:10