Difference between creating a local variable and assigning ivar and directly assigning ivar?

I always wondered why all the Apple code samples use this code:

UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; self.navigationController = aNavigationController; [self.view addSubview:[navigationController view]]; [aNavigationController release]; 

They always create a local variable and assign it to ivar, why not just do it:

 self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];; [self.view addSubview:[navigationController view]]; [navigationController release]; 

Is there another reason, moreover, is it easier to understand? Is this the best practice ?.

-Oscar

+4
source share
5 answers

The replacement code is incorrect and thus illustrates the problem that Apple is trying to prevent. Here is your code:

 self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; [self.view addSubview:[navigationController view]]; [navigationController release]; 

You left me. in your links. Perhaps you wanted to access ivar directly, but in this case you created a very confusing code by mixing accessors and direct access to IVAR (and violated the basic rule using direct access to IVAR outside the accessor). If not, then you intended to write this:

 self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; [self.view addSubview:[self.navigationController view]]; [self.navigationController release]; 

This last line is very wrong. Never send - select the result of a method call. So no, the way you do this is wrong.

However, Apple and I do not agree on how to do this. Here is how I do it:

 self.navigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease; [self.view addSubview:[self.navigationController view]]; 

I like -autorelease because I find that it prevents errors. The more the alloc and release function is allocated, the more likely it is that the developer will introduce a memory leak (for example, by adding a "return"). autorelease avoid this by keeping the save and release together, making the intention to use this as a temporary variable more understandable and, as a rule, greatly simplifies the code review.

Apple generally disagrees with me in its sample code because they emphasize performance using release and outsourcing. I believe that this is an incorrect optimization, since this object will not be freed during this cycle of the cycle in any case (therefore, memory is not saved), and I believe that a very small decrease in the performance of auto-advertising is more compensated by a decrease in memory leaks due to improper use release.

The discussion with auto-advertising and the release is filled with shades of gray (of course, I use the release directly in the cycles), and different developers have different approaches, but your replacement code is not the way to do it anyway.

+2
source

The differences in the first lines are that the Apple version separates the object creation and assignment to ivar, while yours merges them. Conceptually, the Apple version is a little easier to understand. As far as I know, this is not the best practice.

+1
source

Both versions skip checking for nil:

(Assuming self.navigationController is a property preserving its value)

 self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; if (self.navigationController != nil) { [self.view addSubview: navigationController.view; [self.navigationController release]; } 

You can argue that this is a style, but, in my opinion, this leads to fewer errors.

+1
source

It may be the same as in the upper example, but there will be no chance.

remember, that

 self.navigationController = aNavigationController; 

coincides with

 [self setNavigationController:aNavigationController]; 

and you don’t know what is going on inside this setNavigationController method. It could be initializing another object and setting it as an iVar, which you then free, causing a crash.

+1
source

Since it is clear that the code uses the instance variable UINavigationController. Then there would be no reason:

 self.navigationController = aNavigationController 

If you have not saved it.

But if you do it like this:

  self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; 

Then, if you release it as follows:

 [navigationController release]; 

It looks like we are releasing an instance variable that should be saved for the lifetime of the current class that initializes the navigation controller. Thus, it is error prone, which makes newbies think that it should only be released in the dealloc method.

Both approaches will have a counter of 0 at the end. If in the dealloc implementation:

 [navigationController release]; // 1 for the ivar [super dealloc]; // 0 for the retained subviews 
0
source

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


All Articles