Goal c, Managing instance member memory

I am confused about managing the memory of instance members. I have a class with ivar:

DetailedResultsTableViewController *detailedResultsTableViewController; 

and

 @property (nonatomic, retain) DetailedResultsTableViewController *detailedResultsTableViewController; 

in the .m file:

 @synthesize detailedResultsTableViewController; 

and

 [detailedResultsTableViewController release]; 

When I start this variable:

 self.detailedResultsMapViewController = [[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil]; 

I checked the stack right after this init, and it's 2 !!! if I release it at the end of the function, it will fall for an unselected object. What am I doing wrong? how should i start this type of variable? Thanks!!

+3
source share
6 answers

At first you should not look at the amount of the balance, it is not very reliable.

Secondly, your property will be saved. Therefore, when you assign something to it, it will increase the reatincount. Like alloc .

By doing this, you leak:

 self.detailedResultsMapViewController = [[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil]; 

you should:

 DetailedResultsMapViewController *vc = [[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil]; self.detailedResultsMapViewController =vc; [vc release], vc= nil; 

Or use Autorelease:

 self.detailedResultsMapViewController = [[[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil] autorelease]; 
+4
source

Using property and synthesis, you get a new method. In this case, you will have a new set and get method for detailedResultsTableViewController . This is generated for you during compilation (i.e. there is no code you have to add)

This installation method will

 - (void)setDetailedResultsTableViewController:(DetailedResultsTableViewController *)c { if (detailedResultsTableViewController != nil) { [detailedResultsTableViewController release]; detailedResultsTableViewController = nil; } detailedResultsTableViewController = [c retain]; } 

So when you call

 self.detailedResultsMapViewController = [[DetailedResultsMapViewController alloc] init...]; 

What you are actually calling

 [self setDetailedResultsMapViewController:[[DetailedResultsMapViewControler...]]]; 

So, you are actually making two saves. When you call alloc ... init. and then another because you are implicitly calling setDetailedResultsMapViewController, which then also saves.

If you use properties, you should use

 DetailedResultsTableViewController *d = [[DetailedResultsMapViewController alloc] init...] self.detailedResultsMapViewController = d; [d release]; 

The advantage of this is that you do not need to remember the release of the old object before assigning the new one, since the synthesized method does this for you. You can also just do

 self.detailedResultsMapViewController = nil; 

in your dealloc method, and you won’t have to worry if you already released it elsewhere.

This is useful to know because you can override the set method by manually entering code that allows you to do things when objects are set.

+4
source

You are doing the wrong two .

At first:

 self.detailedResultsMapViewController = [[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil]; 

it should be:

 self.detailedResultsMapViewController = [[[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil] autorelease]; 

since you use self.… , you use the semantics of memory management of the property, which in this case is equal to retain , therefore it is saved again.

Secondly:

You used retainCount . Which has nothing to do with debugging memory management.

If you want to know why this is wrong, look at the other answers regarding saveCount right here in Stack Overflow, or read @bbum for a more complete description of why you shouldn't use it.

You violated the rules of memory management by not releasing something that belonged to you. This alone is enough to find the problem in your code. In fact, I am surprised that the static analyzer did not understand this problem.

+2
source

Whenever you declare a property as retain and you reference it with self.myiVar, it will use setter and setter will save the object. In addition, since you are using alloc for the object, this will also increase the hold count to 2, bringing the save count to 2.

As a note, I would not rely too much on keepCount, sometimes it gives incorrect results, but this time it is true.

Here are a few options to avoid having a hold of 2:

 //Refer to it with using the setter detailedResultsMapViewController = [[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil]; //Autorelease it after alloc detailedResultsMapViewController = [[[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil] autorelease]; 
+1
source

When you have a saved property, it increases the save count on any self.myProperty =

Alloc also increases the number of deductions. So in your case, the retention rate is 2.

There a couple comes up.

  • You can include autorun in your init alloc statement
  • Create a temporary variable when you set up your instance, and then when you are done set its property and release temp.
  • Drop yourself. for this assignment. The catch is here, if you have a custom setMyVariable function: then it will not be called without self.
  • Use ARC and you don’t need to worry about it.
+1
source

Your @interface correct, but your implementation is a bit wrong:

 @implmentation MyClass //It good practice to explicitly state the a variable name for this property to use //The common approach is to use the property name with a leading underscore //This prevents accidentally accessing the ivar within the class instead of using the accessor methods. You should only access the ivar directly within the accessor methods (which in these case are being created for you by @synthesize), in the designate init method and dealloc @synthesize detailedResultsTableViewController = _detailedResultsTableViewController; -(void)dealloc { //... [_detailedResultsTableViewController release]; //... } @end 

When accessing a property:

 myClass.detailedResultsMapViewController = [[[DetailedResultsMapViewController alloc] initWithNibName:@"DetailedResultsMapViewController" bundle:nil] autorelease]; 

The code setting the method does not "own" the new value, so it must autorelease .

+1
source

Source: https://habr.com/ru/post/910807/


All Articles