Should I release instance variables and properties in dealloc? - objective-c

According to Apple's documentation on the View Controller Lifecycle I noticed the following regarding the dealloc method:
Override this method only to perform any last-minute cleanup of your
view controller class. Objects stored in instance variables and
properties are automatically released; you do not need to release them
explicitly.
I've been taught always to call release on instance variables and properties that I own in my view controller's dealloc method.
The only exception I was aware of is when using ARC but it does not mention ARC in this documentation.
Is this correct?

Since the guide you posted was updated recently, I'm pretty sure that it assumes you're using ARC (you should do that, after all, if possible).
You're correct, before ARC, you had to release your instance variables in the dealloc method (you can see that in the old XCode templates in the dealloc of the App-Delegate). With ARC, this gets handled automatically (as this guide says), so except for special needs, the dealloc method is not used anymore.

As JiaYow mentions, that guide has been updated to ARC. Here you can find the Legacy guide for view controllers: https://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewControllerPGforiOSLegacy/BasicViewControllers/BasicViewControllers.html#//apple_ref/doc/uid/TP40011381-CH101-SW1

Related

What kind of property should be set to nil in dealloc?

I'm using ARC. Will ARC automatically release all the properties in dealloc? Is it necessary to manual set all public properties and private field to nil? Are there any good pattern to follow?
Under ARC, the pattern is... don't do anything in dealloc, or even implement it. ARC takes care of your properties and instance variables for you.
The only exception is that dealloc is a good place to unregister for notifications, if your object has registered for any.
Good question. When using ARC the compiler will implement a dealloc method for you and will handle implicitly the release of your instance variables and properties.
You may still need a custom -dealloc if your class needs to do anything other than releasing memory (e.g unregister for notifications like jrturton mentioned).
You can get a good grasp of what's you need to consider when transitioning to ARC in those Apple official notes.

Override "release" or "dealloc"

Which is the best method
Override "release" or "dealloc" method in objective c?
why?
Under non-ARC, 99% of the cases you should not override the release method.
I have seen only 1 case that the need to override the release method - a kind of singleton, which forces the class have really 1 single instance no matter how many times you call alloc.
That way override not only the release method, but also allowWithZone:, retain, 'retainCount`, etc. (It is actually not common to implement that kind of singleton)
Which is the best method? Override the release or the dealloc method?
- dealloc, definitely. You should never override - release.
Why?
One, because release does a bunch of internal stuff. Two, because if release is called, it does not mean that the object is deallocated.
So you would release your ivars or null your properties by accident. And who wants an ugly segfault when we can have worldpeace instead?
If an object is really deallocated, - dealloc will be called.
If you are not using ARC, you should override the -[MyObject dealloc] dealloc method to release all retained objects inside your object. I have never found a case where I needed to override the release method.
If you are using ARC, you can usually avoid overriding the -dealloc method at all, unless you are using anything that ARC won't free up like a sqlite pointer or something.
dont override either for anything not relating to memory management - you dont when and if those methods even get called.
exceptions for when you should dealloc:
removing KVO / notification center observer
deallocating manually allocated memory (arc) / release your ivars (non-arc)

How to manage unsafe_unretained ivars/properties?

I started objective-c and iOS a couple of weeks ago (worth bearing in mind), and I apologise in advance for the awful diagram!!
The above diagram shows the structure of my calls to a webservice. Thin arrows denote an object creating another object, whereas thick arrows denote an object holding a strong (retained) reference to the pointed-to object.
I believe that this contains what is called a "circular reference" and will create problems when it comes to deallocating the objects.
I understand that the easy answer would be to replace some of the strong references to weak ones, which I'd love to do, except my project is also targeting iOS 3.2 (not my decision - I can't really change this fact!). So, I think I'm right in saying that I have to use __unsafe_unretained instead, but I'm quite worried about the fact that these won't auto-zero, as I'll end up with EXC_BAD_ACCESS problems when objects get deallocated...
So my problem is firstly that I have circular references. To solve, I would have to use __unsafe_unretained, which leads to my second problem: How to correctly manage these?
A question that might be related is: How does NSURLConnection manage it's strong references? I have heard from various sources that it retains its delegate? So...if I retain an NSURLConnection, (and am also its delegate) and it retains me, this would also be a circular reference, no? How does it get around my problem?
Any advice is very welcome!
Regards,
Nick
When a parent has a reference to a child object, it should use a strong reference. When a child has a reference to it's parent object, it should use a weak reference, aka unsafe_unretained.
By convention, delegate relationships in iOS are usually weak references, so you'll find that most delegate properties on Apple's own classes are declared as unsafe_unretained.
So your controller retains the services that it is using, but the services only weakly link back to the controller. That way, if the controller is released, the whole lot can be safely disposed of without any circular references.
The danger with this is that if the web service is doing some long-running task, and the controller gets released before it has finished, the service is left with a dangling pointer to it's now-deallocated delegate. If it tries to send a message to the delegate, such as "I have finished" it will crash.
There are a few approaches to help solve this (they aren't mutually exclusive - you should try to do them all whenever possible):
1) Always set the delegate properties of your services to nil in your controller's dealloc method. This ensures that when the controller is released, the delegate references to it are set to nil (sort of a crude, manual equivalent of what ARC's weak references do automatically).
2) When creating your own service classes that have delegates, make them retain their delegate while they are running and then release the delegate when they are done. That way the delegate object can't get deallocated while the service is still sending it messages, but it will still get released once the service has finished (NSTimer's and NSURLConnections both work this way - they retain their delegate while they are running and release it when they are done).
3) Try not to have long-running services owned by something transient like a view controller. Consider creating singleton objects (shared static object instances) that own your services, that way the service can do it's job in the background regardless of what's going on in the view layer. The controller can still call the service, but doesn't own it - the service is owned by a static object that will exist for the duration that the app is running, and so there's no risk of leaks or premature releases. The service can communicate with the controller via NSNotifications instead of delegate calls, so there is no need for it to have a reference to an object that may vanish. NSNotifications are a great way to communicate between multiple classes without creating circular references.
All of your questions and concerns are correct, and this problem with the previous use of assign (now better named __unsafe_unretained) is why Apple developed auto-zeroing for weak. But we've dealt reasonably safely with assign delegates for many years, so as you suspect, there are ways to do it.
First, as a matter of practice, you should always clear yourself as the delegate when your release an object you were delegate for. Pre-ARC, this was traditionally done in dealloc:
- (void)dealloc {
[tableView_ setDelegate:nil];
[tableView_ release];
tableView_ = nil;
}
You should still include that setDelegate:nil in your dealloc if delegate is __unsafe_unretained. This will address the most common form of the problem (when the delegate is deallocated before the delegating object).
Regarding NSURLConnection, you are also correct that it retains its delegate. This is ok because it has a lifespan typically much shorter than its delegate (versus a table view delegate which almost always has the same lifespan as the table view). See " How to work around/handle delegation EXC_BAD_ACCESS errors? Obj C " for more discussion on this in a pre-ARC context (the same concepts apply in the new world of strong/weak).

Can I just release the top object (iPhone)?

If I release the object that's holding a reference to the variable that I need to release, is that sufficient? Or must I release at every level of the containment hierarchy? I fear that my logic comes from working with a garbage collector for too long.
For instance, I assigned to this property of a UIPickerView instance by hand instead of using IB
#property(nonatomic, assign) id<UIPickerViewDelegate> delegate
Since it's an assign property, I can't just release the reference after I assign it. When I finally release my UIPickerView instance, do I need to do this:
[singlePicker.delegate release];
[singlePicker release];
or is the second line sufficient?
Also: Are these assign properties the norm, or is that mostly for Interface Builder? I thought that retain properties were the normal thing to expect.
The properties are declared assign instead of retain for a reason - delegates are not owned by their holders and they don't call release on them. Otherwise there would be a problem with circular references. You however have to call release on the object you use as the delegate somewhere if you own them.
If delegates were retained, imagine the following situation:
a takes b as a delegate, retains b
b takes a as a delegate, retains a
Now you have a circular reference - without ugly cleanup code that explicitly tells them to release their delegates, both of the objects will never be deallocated.
The subject is treated in Delegation and the Cocoa Application Frameworks:
Delegating objects do not (and should not) retain their delegates. However, clients of delegating objects (applications, usually) are responsible for ensuring that their delegates are around to receive delegation messages. To do this, they may have to retain the delegate in memory-managed code. This precaution applies equally to data sources, notification observers, and targets of action messages. Note that in a garbage-collection environment, the reference to the delegate is strong because the retain-cycle problem does not apply.

Objective-C Delegate Pointers

If we write the following code:
ExplorerAppDelegate * appDelegate = (ExplorerAppDelegate *)[[UIApplication sharedApplication] delegate];
This makes a reference to the original delegate pointer, but:
Does it increase the reference count?
Do we have to explicitly call as [ExplorerAppDelegate retain] right after, or not at all?
What's happening, exactly?
After we've used this, we should also do a [ExplorerAppDelegate release] in the dealloc method, right?
No, it does not increase the retain count.
The convention in Objective-C is that objects you are given should be memory managed by yourself - but in the case of obtaining a shared common resource like the app delegate, the memory is maintained elsewhere and of course (with this being the app delegate) you know that it will always be "alive" as long as your class is... so there is no need to retain the reference.
In most uses of delegates, instead of fetching a delegate you are given one, and that reference is not retained either. In that case whoever gave you the delegate is also responsive for clearing out the delegate link before the delegate is released.
The reason you don't want to generally retain delegate references is that it can prevent some objects from being deallocated, for instance if one class is a delegate of a class that ues the other class as a delegate.
The reference count will not be increased
You should retain it if you want to be sure that it isn't deallocated while you have a pointer to it
You should only release it if you retained it
So basically, if you're only using the object in a single function, you probably don't need retain or release it. If it exists when you get it, then it's (probably) not going to be deallocated by the end of the function. If you're keeping it around, in an ivar (member variable) for example, then you should retain it and release it later.
See the "Weak References to Objects" in Memory Management Programming Guide for Cocoa for the official answer. Pointers to delegates are one of the possible exception cases to the memory management rules.