this article reprinted to http://blog.sina.com.cn/s/blog_a843a8850101ds8j.html
(i). About Nil
http://cocoadevcentral.com/d/learn_objectivec/
Calling Methods on Nil
In Objective-c, the nil object was the functional equivalent to the NULLpointer in many and other languages.
The difference is so you can call methods on nil without crashing or throwing an exception.
In Objective-c, the nil object has the same function as a null pointer in many other languages.
The difference is that you can send any message to a nil object that allows a nil object to call any method without causing the program to crash or throw an exception.
This is a useful basic knowledge
Also at the Cocoachina (http://www.cocoachina.com/bbs/read.php?tid-70288.html) forum, it was noted that
After the object is released, the system will mark the block memory as available (assignable) nil is the role of a reset pointer to memory release meaningless
Prevents a call error from occurring.
(ii). CONCLUSION:
Using different code handling in different environments is the mean,
If you are developing and debugging, the test phase
Use the DEALLOC process that directly exposes the problem code:
In Dealloc, just release your variables.
If you publish the program to the user, use the first release, then the value of nil after the way
This will not expose crash to the user
(c).. Here are the references:
First of all, this is a very good blog, a detailed explanation of the dealloc of several processing methods of argumentation
Http://iphonedevelopment.blogspot.com/2010/09/dealloc.html
English good to see the original text, do not be misunderstood by my translation.
Other than that:
StackOverflow has several valuable references that discuss the developer's experience in this area:
Http://stackoverflow.com/questions/4124049/dealloc-use-release-or-set-to-nil-for-properties
Http://stackoverflow.com/questions/192721/why-shouldnt-i-use-objective-c-2-0-accessors-in-init-dealloc
(d). Now, officially translated to this blog: http://iphonedevelopment.blogspot.com/2010/09/dealloc.html
Statement: If there is a wrong translation or typo, please point out, but I am only a translation for learning to explore the use of any problems and disputes in my own unrelated, thank you for your cooperation!
Dealloc
Last week there is a bit of a Twitter in-fight in the IOS community over the ' right ' to release your instance VARIABL Es in Dealloc. I think Rob actually started it, to being honest, but I probably shouldn ' t being bringing that up.
Last week, there was a heated discussion in the Twitter IOS community about any correctly releasing your variables in the Dealloc method (Debate war!). I think it was caused by Rob, but to be honest, I shouldn't have disclosed it (funny, the author didn't want to gossip, but still gave Rob a connection).
Basically, several developers were claiming, there ' s never a reason to set an instance variable to nil in Dealloc, whi Le others were arguing that's should always does so.
Basically, several developers have stated that there is no reason to allow an instance variable to be set to nil in the Dealloc method, while others argue that you should do so, in Dealloc, where the instance variable is assigned nil.
To me, there didn ' t seem to be a clear and compelling winner between the approaches. I ' ve used both in my career. However, since we ' re in the process of trying to decide which approach to use in the next edition of Beginning IPhone Deve Lopment, I reached out to Apple's Developer Tools evangelist, Michael Jurewitz, to see if there is an official or recomme nded approach to handling instance variables in Dealloc.
For me, there seems to be no clear and complete winner in either of these ways. In my development process, I have used both of these methods. But now that we're trying to take these two methods to the next version of the Beginning IPhone development, I asked Apple's developer, Michael Jurewitz, to find out how to deal with instance variables in Dealloc, Whether there is an official or recommended method.
Other than the fact that you should never, ever use mutators in Dealloc (or INIT, for that matter), Apple does is not having an Official recommendation on the subject.
In addition to the Dealloc or Init method, you should not use the Set Value method (Eg:[self.xxxx message), Apple did not provide an official recommendation for releasing instance variables in Dealloc.
However, Michael and Matt drance of Bookhouse Software and a former evangelist himself, had discussed this issue extensive Ly last week. They kindly shared their conclusions with me and said it is okay for me to turn it into a blog post. So, here it is. Hopefully, I ' ve captured everything correctly.
However, Michael and Matt drance of Bookhouse Software and a former evangelist himself (evangelist intended to spread the gospel, I guess the people who preach Apple's official technology, is to popularize the Apple development technology of some experts it) on this issue in the last week, a more extensive discussion. They were very good at sharing their conclusions with me and agreed that I would publish them on the blog, so the result is this, hopefully I've collected everything correctly.
The Major Approachs
Just to make sure we ' re all on the same page and let's look at the and the approaches that made up the the and the different of the Argument last week.
The two main methods
First of all to confirm our consensus, let's take a look at two different supporters of last week's two ways.
Just Release
Just release
The more traditional approach are to simply release your instance variables and leave them pointing to the released (and PO tentially deallocated) object, like so:
The most traditional approach is to simply release your instance variable and let it just think of an object that is already on the release, like this:
- -(void) dealloc
- {
- [Sneezy release];
- [Sleepy release];
- [Dopey release];
- [Doc release];
- [Happy release];
- [Bashful release];
- [Grumpy release];
- [Super Dealloc];
- }
In this approach, each of the pointers is pointing to a potentialy invalid object for a very short period of time-u Ntil the method Returns-at which point the instance variable would disappear along with its owning object. In a single-threaded application (the pointer would has to being accessed by something triggered by code in either this Obje CT's implementation of dealloc or in the dealloc of one of their superclasses, there ' s very little chance that the instance Variables'll be used before they go away, which are probably what have led to the proclamations made by several that ther E ' s "No value in setting instance variables to nil" in Dealloc.
In this method, each pointer will point to a potentially illegal object in a very short time, knowing that the method is executed, and then the instance variable disappears with its owner. In a single-threaded application (the pointer would have to be either the object's own implementation dealloc or something started in the dealloc of its parent class), an instance variable would be used to be a small probability event before it was trivial. But if it happens, it will be just kind, which is the concern of those who declare that they need to be assigned a value in the Dealloc method to the nil value of the instance variable.
In a multi-threaded environment, however, there are a very real possibility that the pointer would be accessed between the T The IME is deallocated and the time of the its object are done being deallocated. Generally speaking, this was only going-happen if you've got a bug elsewhere in your code, but let's face it, you may ve Ry well. Anyone who codes on the assumption, then all of their code is perfect are begging for a smackdown, and Xcode ' s just biding I TS time waiting for the opportunity.
However, in a multithreaded environment, a pointer is accessed before it is dealloc and its owner object is dealloc, but it is a very likely thing to happen. In general, if you encounter bugs elsewhere in the code, this is the source of the problem, but let's face it and you'll get better. Any person who builds code that is perfect in their own code is in deceiving, and Xcode is just waiting for an opportunity to give you an error.
Release and Nil
The last few years, another approach to dealloc have become more common. In this approach, your release your instance variable and then immediately set them to nil before releasing the next Instan CE variable. It ' s common to actually put the release and the assignment to nil on the same line separated by a comma rather than on con Secutive lines separated by semicolons, though that ' s purely stylistic and have no affect on the the-the-the-the-the-the-the-the-code is compiled. Here's what we previous Dealloc method might look like using the This approach:
In the past few years, another approach that has been dealt with in dealloc has become more prevalent, and in this approach, You release your instance variable and assign it to nil immediately before releasing the next instance variable. It is common practice to separate the release statement from the assignment nil statement with one line instead of a semicolon separated into multiple lines, although this is only the appearance of the surface code, and at compile time there is no The difference. Here's what our previous dealloc looked like after using this method:
- - (void) dealloc
- {
- [sneezy release], sneezy = nil;
- [sleepy release], sleepy = nil;
- [dopey release], dopey = nil;
- [doc release], doc = nil;
- [happy release], happy = nil;
- [bashful release], bashful = nil;
- [grumpy release], grumpy = nil;
- [super dealloc];
- }
In this case, if some piece of code accesses a pointer between the time that Dealloc begins and the object are actually DEA Llocated, it'll almost certainly fail gracefully because sending messages to nil are perfectly okay in objective-c. However, you ' re doing a tiny bit of the extra work by assigning nil to a bunch of pointers that is going to go away Momentari Ly, and you ' re creating a little bit of the extra typing for yourself in every class.
In this case, if there is code to access a pointer that is dealloc but not yet fully dealloc, such an operation is invalid because in objective-c, it is no problem to send a message to an object that wants a nil value and does not raise an error. However, if you assign a value of nil to some objects that will disappear immediately, you do some extra work to create these extra input expenses in each of your classes.
The Showdown last war so, here's the real truth of the matter:the vast majority of the time, it's not going to make any notice Able difference whatsoever. If you ' re not accessing instance variables that has been released, there ' s simply not going to is any difference in the B Ehavior between the approaches. If You is, however, then the question Is:what does you want to happen when your code does this bad thing?
So, next is the most important place. Most of the time, there is no obvious difference. If you do not access the instance variables that are released, there is no difference in the functional aspects between the two methods. But if you visit, then the question is, how do you want your code to respond to this situation?
In the first approach, your application would usually crash with a exc_bad_access, though you could also end up with any m Anner of odd behavior (which we call a "heisenbug") if the released object was deallocated and its memory are then reused fo R another object owned by your application. In those cases, you could get a selector not recognized exception when the message was sent to the Deallocated object, or you May simply get unexpected behavior from the same method being called on the wrong object.
In the first way, your program usually crashes and warns you exc_bad_access, although you may end up with some weird results (usually we call it heisenbug, this bug is weird, and it's usually bad to reproduce, To be difficult to fix) like a released object being dealloced and its memory being exploited by another object in your dashed virtual. In this case, you may get an selector not recognized exception, and when the message is sent to an object that is delloced, or after the wrong object executes the method you called, you may just get an exception result.
In the other approach, your application would quietly send a message to nil and go on its merry, generally without a Crash or any other immediately identifiable problem.
In another way, your program sends a message to a nil-valued object and it just doesn't happen-nothing happens, no program crashes (no crash!! ), there is no other real-time discernible problem to appear.
The former approach is actually good when you ' re developing, debugging, and doing unit testing, because it makes it easier To find your problematic code. On the other hand, that's approach is really, really bad in a shipping application because you really don ' t want-crash on Your users if you can avoid it.
The previous method will be more advantageous when you are developing, debugging, or doing unit testing. Because it will make it easy for you to find the problem code. On the other hand, this method can be very, very bad, after you publish your program, because you do not want your users to encounter the program crash and this is the crash! you can avoid.
The latter approach, conversely, can hide bugs during development, but handles those bugs more gracefully when they happen , and you ' re far from less likely to the your application go up in a big ball of the fire in front of your users.
The latter method, on the contrary, obscures your bugs during development, but is treated more gently when bugs occurs, but at the same time you make it more or less possible for your program to be wrapped in fireballs and presented to your users.
The Winner? Winner? There really isn ' t a clear cut winner, which is probably why Apple doesn ' t has an official recommendation or stance. During their discussion, Matt and Michael came up with a ' best of both worlds ' solution, but it requires a fair bit of Ext RA code over either of the common approaches.
There's no obvious winner, and maybe that's why Apple doesn't give an official recommendation or example. During their discussions, Matt and Michael came up with a tradeoff between two scenarios that would make the program a better and more robust solution, but this would require some extra code, based on both of these usual methods.
If you want your application to crash when a released pointer is accessed during development and debugging, the solution I s to use the traditional approach in your debug configuration. If you want your application to degrade gracefully for your users, the solution are to use the newer approach in your Relea SE and ad hoc configurations.
During your development and commissioning, when a pointer is accessed, if you want your program to crash directly, the solution is to use the most traditional method in your debugging environment. If you want your program to be friendly to the user, the workaround is to use the new method in your release and add the extra configuration.
One somewhat pedantic implementation of this approach would is this:
A more rigid approach to implementing this theory would be like this:
-(void) Dealloc {#if DEBUG [sneezy release]; [Sleepy release]; [Dopey release]; [Docrelease]; [Happy release]; [Bashful release]; [Grumpy release]; [Super Dealloc]; #else [Sneezy release], sneezy = nil; [Sleepy release], sleepy = nil; [Dopeyrelease], dopey = nil; [Doc release], doc = nil; [Happy release], happy = nil; [Bashful release], bashful = nil; [Grumpy release], grumpy = nil; [Super Dealloc]; #endif}
That code assumes this your debug configuration has a precompiler definition of debug, which you usually had to add to yo ur xcode project-most xcode project templates do not provide it for you. There is several ways you can add it and I typically just use the
Preprocessor Macrossetting in the project ' s Build
This code assumes that you have a precompiled macro definition in your debug configuration and that you have to add it to your Xcode project, and most of the Xcode project templates will not be available to you. There are several ways to add, but representative, I only use the precompiled macro set value under Project build
Configuration:
Although the code above does, indeed, give us the best of both worlds-a crash during development and debugging and grace Ful degrading for customers-it at least doubles the amount of code we had to write in every class. We can do better than that, though. How about a little macro magic? If we add the following macro to our project ' s. pch file:
Although the above code gives us the tradeoff, that is, the program will be crash during development and debugging, but will be handled smoothly when it is released to the user. But it uses more than twice times the original code in every one of our classes. We can do better, how about using some macros? If we add the following macro variable to the. pch file:
- #if DEBUG
- #define MCRELEASE (x) [x release]
- #else
- #define MCRELEASE (x) [x release], x = Nil
- #endif
We can then use this macro in Dealloc, and our best-of-both-worlds code becomes much shorter and more readable:
We can use them in dealloc, and our "tradeoffs" become shorter and easier to read:
-(void) Dealloc {mcrelease (sneezy); Mcrelease (sleepy); Mcrelease (dopey); Mcrelease (DOC); Mcrelease (happy); Mcrelease (bashful); Mcrelease (grumpy); [Superdealloc]; }
Once you ' ve got the macro in your project, this option was actually no more work or typing than either of the other Dealloc Methods.
Once you have written a macro in your project, this option will not cost you extra work than the previous two dealloc methods.
But, know? If you want to keep doing it the the the-the-I always-done it, it's really fine, regardless of which-the-do it. If you ' re consistent in your use and is aware of the tradeoffs, there ' s really no compelling reason to use one over the O Ther outside of personal preference.
But you know what? It's also good if you want to keep the way you're dealing with objects in Dealloc. Whichever way you are now, if you use it and realize the pros and cons of it, there is really a compelling reason to make a person change his or her personal choice.
So, in other words, it's kind of a silly thing for us all to argue over, especially when there ' s already politics, religio NS, and sports to fill that role.
So, in other words, we don't have to argue anymore, there are too many things to argue about, like policy, race, sports ...
The garbage Collection Angle there ' s one last point I want to address. I ' ve heard a few times from different people, setting an instance variable to nil Indealloc acts as a hint to the garb Age collector If you ' re using the-allowed-not-required GC option (when the required option is being used, dealloc isn ' t Even called, Finalize is). If This were true, forward compatibility would is another possible argument for preferring the newer approach to Dealloc O Ver the traditional approach.
And one last thing I want to point out. Several times I've heard from different people that assigning a value to an instance variable in the Dealloc method will play a role in giving the garbage collector a hook when you use the allowed-not-required GC option (when Required-option is used, Dealloc not be called, Finalize will). If this is true, forward compatibility will become a new argument against the new approach in dealloc and the traditional approach.
While the It is true, the Java and some other languages with garbage collection, nulling out a pointer this you ' re-done wit H helps the garbage collector know that's you ' re do with this object, so it's not altogether unlikely that Objective-c ' s G Arbage collector Does the same thing, however any benefit to nil ' ing out instance variables once we get garbage collection In IOS would is marginal at best. I Haven ' t been able to find anything authoritative which supports this claim, but even if it ' s 100% true, it seems likely t Hat when the owning object is deallocated a few instructions later, the garbage collector would realize that the deallocate D object is do with anything it was using.
In Java and some other languages that have garbage collection mechanisms, assigning a pointer to NULL will help you let the garbage collector know that you've run out of this object, and they're not equivalent to Objective-c's garbage collector doing the same thing, but using nil to assign value to the instance variable benefits, Once it was an iOS garbage collection mechanism, it became quite marginalized. I could not find any authoritative arguments to support this statement, but even if it is hundred percent true, it seems that when an owned object is executed by the instruction Dealloc, the garbage collector will realize that the object being Dealloc has done all that it has to do.
If there is a benefit in this scenario, which seems unlikely, it seems like it would being such a tiny difference that it Wou LDN ' t even make sense to factor it into your decision. That being said, I has no firm evidence one-on-one, and the other in this issue and would welcome being enlightened.
There is no benefit in this situation, it seems that there is no ... It doesn't seem to be a reference to your decision to use that approach. In other words, I have no strong evidence to welcome the discussion of mutual inspiration on this issue.
Variable release processing in the Dealloc method of objective-c memory management