Order of release and dealloc messages - iphone

What is the recommended way of doing this. Should I call super dealloc first or last or doesn't it matter?
- (void)dealloc
{
[super dealloc];
[orderNumber release];
[orderDate release];
}
Also when it comes to overriding methods like didViewLoad - should I call super first or last?

Always call [super dealloc] last or you might easily come into trouble because you're working on a stale object.
With didViewLoad you normally call it before your own code as you want the standard initialization stuff executed before. I've seen examples in Apple's code that don't call the super implementation at all, though, so maybe there's not much going on anyway.

In this case call the super after you have released all your properties/iVars. For viewDidLoad/willAppear/etc. I usually call the super first. The order matters when your custom class is relying on an object that is created by the super. For the default viewDidLoad this is not the case so it is preference(I believe).

There is no general rule - you chose to override the method, what does it do? Do you want it to happen before or after your custom implementation?
didViewLoad doesn't appear to be a real method.
We know that [super dealloc] destroys the current object completely, so any code that comes after it is wrong. So, in this case, call [super dealloc] last.

The pointers orderNumber and orderDate are held inside your object.
[super dealloc] deallocates your object (aka self).
Once you deallocate your object you must not rely on the things inside it (e.g. orderNumber) having the values they did before you deallocated it.
Therefore, deallocate the members before deallocating the self object.
The opposite holds true for init functions - you can't initialise the pointers until after your object is constructed, so [super init] comes before you initialise the members.

Regarding viewDidLoad (et al), you do whatever works. If you have stuff you want to happen before the superclass does its thing, then you do it before you call the superclass method, and likewise for stuff you want to happen afterwards.
If you don't know whether your code should run before or after, then it probably doesn't matter.

Related

Object c property dealloc, which one is correct? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dealloc method in iOS and setting objects to nil
As to property dealloc in object c, i have seen different kinds of forms. Which of following is best/correct
//Kind1:
- (void)dealloc
{
[_property release];
[super dealloc];
}
//Kind2:
- (void)dealloc
{
self.property = nil;
[super dealloc];
}
//Kind3:
- (void)dealloc
{
[_property release]; _property = nil;
[super dealloc];
}
Your second option is inadvisable. Property setters may have side-effects and generally aren't implemented with the consideration that the object may be half torn down already. In general you should avoid any method calls to self (or super) from dealloc, other than [super dealloc]. You should also avoid non-trivial calls (i.e. anything but release) on other objects, as you may have circular references that can lead back to references to your half-deallocated object.
The first option is perfectly sufficient. Note that if you use ARC it is redundant. Using ARC is your best bet, invariably, as it's not only safer but faster.
The third option is controversial. Some people argue that it makes your program more resilient to errors (since references after dealloc may end at the zeroed instance variable, rather than bouncing through it and seg faulting, or worse). They also argue that it ensures that if you do run a method which tries to use the value, it'll probably fail gracefully (again, rather than dereferencing what is a dangling pointer at that point). But if you subscribe to my first point on avoiding this to begin with, it becomes somewhat moot. And my experience is that relying on that behaviour is a bad idea - even if it's a clean design to begin with, it's easy to forget about it and end up changing the code some time later, in a way that breaks it.
And those that dislike the third option also argue that it hides errors. Some go as far as explicitly overwriting not with nil but rather an obviously bogus value (e.g. 0x0badf00d) to make it clearer if and when a dangling pointer is dereferenced.
Kind1 is more than enough;
It is usually not a good idea to use 'self' on alloc and dealloc. coz self will call setter/getter method, and if u have custom setter/getter method its can cause trouble.
You should never call self. in dealloc.
Once you have release-ed then there is no advantage whatsoever of making it nil.
So, first one is the correct way to use dealloc.

Objective C ARC equivalent for self?

What is the equivalent keyword i can use in the place of self in ARC enabled projects?
ex:- [self mymethod]; what is ARC equivalent of this method call?
I don't quite get it? Why ARC should have different syntax for method calls? It is an automatic memory management, where in most cases you won't need to use retain/release, nothing more. So it would look like this:
[self mymethod];
In ARC(Automatic Reference Counting),you don't need to release or retain. It has nothing to do with calling methods!
ARC - Automatic Reference Counting implements automatic memory management for Objective-C objects and blocks, freeing the programmer from the need explicitly insert retains and releases. Since this is handled at compile time, no collector process is need to continually clear memory and remove unreferenced objects.
For calling a method, you still do it this way:[self mymethod];
it's still the same
[self myMethod];
But in ARC environment, IIRC, you need to do it like this: (I don't know if this is the source of your question, but when I migrated the first time to ARC, I get compile error if I'm not doing this).
#interface myController()
- (void)myMethod; // you need to declare the method here, if you haven't declared it on the .h
#end
#implementation
- (void)viewDidLoad
{
[super viewDidLoad];
[self myMethod];
}
- (void)myMethod
{
NSLog(#"!");
}
#end
hope this help

Iphone App crashes when releasing view controller containing scrolling UITableView

This is a very very... very odd bug. It's hard to describe the exact project I have, but I will try and create a simpler representation of the classes I have. It goes like this:
Assume I have a navigation controller as my top view controller. Inside it, at one moment in time I have a UIViewController, let's say a ContactsScreenController. The view for this contains multiple UITableView that each is controlled by a separate object of type MyTableController (delegate&datasource). I do this by keeping an array of controllers
// This is the interface for my screen controller. An object of this type goes in a top-
// level navigation controller
// MainScreenController.h
#interface ContactsScreenController : UIViewController
NSMutableArray* tableControllers;
#end
// MainScreenController.m
- (UITableViewCell*)cellForRowAtIndexPath..something..
{
// Here what I do is create a new controller if needed, and add it to tableControllers
// Memory allocations & releases are good because I checked with instruments
}
#define SAFE_DEL(x) { if (x != nil) { [x release]; x = nil; } }
- (void)dealloc
{
SAFE_DEL(tableControllers);
[super dealloc];
}
Now, MyTableController is a more complicated object as it handles fetching data from a web service, but basically what I do is I want to make sure that when the object is deleted, I cancel any pending data requests, like this:
// MyTableController.m
- (void)dealloc
{
[globalDataProvider cancelRequestsForController:self];
// release other objects i might have
[super dealloc];
}
OK, so this is my objects setup. The crash occurs when I am deleting the object tableControllers. It decrements the retainCount for my MyTableController objects and it reaches 0 (checked using Instruments). But for some UNKNOWN reason, I get calls for cancelRequestsForController, AFTER the retain count has been zero.
Obviously, I get a EXC_BAD_ACCESS.
Before you start thinking it's a problem with my retain/release pairs, the application runs perfectly if I am releasing the main screen controller while the inner tables are static. As soon as the are scrolling and I hit the Back button in the navigation controller I experience the bug.
I've checked using instruments the entire history of retain count changes for my inner controllers and it is good (no unusual stuff). When the bug occurs, my last entry in the history is from QuartzCore run_animation_callbacks with a retain count of -1.
Any ideas? :)
PS: As a quick solution to get the project going, I've moved the cancelRequestsForController in a separate method and I'm manually calling it for each object in tableControllers before the release. This way I am sure that there will be no calls after the release, no matter the state of the tableview.
- (void)dealloc
{
for (TableController* c in tableControllers)
[c cancelRequests];
SAFE_DEL(tableControllers);
[super dealloc];
}
But I don't like this solution for several reasons.
Thanks to everybody for the answers/comments.
The problem was generated by a call to [super dealloc] in an object, before I got the chance to release my objects. This caused a lot of crazy stuff to happen. I moved the [super dealloc] at the end of my dealloc method (after my releases) and it works fine now.
The SAFE_DEL macro is unnecessary and makes the code less readable. Simply do:
[someObject release], someObject = nil;
It won't matter if someObject is already nil and it makes the code more directly readable.
As soon as the are scrolling and I hit
the Back button in the navigation
controller I experience the bug.
Any time you have non-memory management logic, you have fragility. Namely, when dealloc is being executed, it is quite likely because there is an entire sub-graph of objects in your application that are being deallocated. Since deallocation order is largely non-deterministic, you can't safely trigger any complex behavior in dealloc without risk that you are going to message an already deallocated object.
The best solution would be to get that cancellation mechanism out of dealloc!
Two things to check:
1. does your globalDataProvider (or any other class for that matter) have a reference to your controller (i.e. to call it back with data?) Your retain counts could be zero but for the wrong reason. How are you allocating the array, as well as each controller in the array? Do you have #properties?
2. In your executables properties Arguements screen, set NSZombieEnabled=YES That will tell you exactly which object is being called when it has a zero retain count.
HTH,
-Mike

Assigning ivars using self keyword in an object's init method

I've read that it's bad to use self.ivar = (convenience method) in and object's 'init' method, as this messes with inheritance.
However, if you know you're not going to subclass your object, is it ok to use the self keyword assignment?
i.e. self.iVar = [Object objectConvenienceMethod];
The reason I ask is this. I create a new object with its own init method, and in that method, I perform various initial assignments. Since I don't use the self keyword, I assign them directly to the iVars, and therefore use the alloc methods rather than the convenience methods. I.e.
iVar = [[Object alloc] init];
Or if I use a convenience method, I retain it. I.e.
iVar = [[Object convenienceMethod]retain]
But... when I run my program with the memory leak tool on, all of these assignments are identified as memory leaks.
If I can use the self keyword plus a convenience method instead of alloc-init, then this would avoid the problem.
If I choose to use the alloc-init approach though, where am I supposed to release the iVars?? Just in dealloc?
Thanks for your help :)
Michael
No, because it isn't only subclass behavior you need to take into account — superclass implementations and even the behavior of code generated by the framework (e.g. synthesized accessors and the black magic used to implement KVO) can also cause trouble. It will probably be OK, but that's still a significant chance of being not-OK. All in all, it's best just to follow Apple's recommendation and assign directly.
Assigning to ivars in init shouldn't be reported as leaks in a properly functioning program. If you're seeing that, there's some other problem that you need to address. Try reducing the problem to a minimal case that we can try out and ask about that — then we can tell what's wrong.
If you alloc or retain them in your class's init method, you should release them in the corresponding dealloc method.
I am thinking your "enclosing" class is not being released, and hence its dealloc method is not being called resulting in your iVars not being released.

What does [super viewWillAppear] do, and when is it required?

-(void)viewWillAppear:(BOOL)animated{
//something here
[super viewWillAppear];
}
Is [super viewWillAppear]; always required? If not when and why do you use it?
First of all, the correct boiler plate should be:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//something here
}
In other words, call super first, then do your own thing. And you have to pass the animated parameter to super.
You usually want to call the super class' implementation first in any method. In many languages it's required. In Objective-C it's not, but you can easily run into trouble if you don't put it at the top of your method. (That said, I sometimes break this pattern.)
Is calling super's implementation required? In the case of this particular method you could get unexpected behavior if you don't call it (especially if you have subclassed a UINavigationController for example). So the answer is no not in a technical sense, but you should probably always do it.
However, in many other methods there may be good reasons for not calling super.
Calling super method provide possibility to execute code in parent class.
Regarding your question according to Apple doc
So, yes, this method required.
In my experience, calling [super viewWillAppear] in the first line, when calling reloadData after that, makes it impossible to retrieve the previously selected row when coming back from a detail view. When [super viewWillAppear] is the last sentence, you can get the selected row and show the previously selected row hint. This happens only when using [tableView reloadData] inside viewWillAppear.
Lets say you have 2 class, a Parent and a Child. Child inherits from Parent. They have a method called greet which returns a string.
Here is what the parent method looks like:
Code:
-(NSString *)greet {
return #"Hello";
}
We want the child to learn from his parents. So we use super to say greet how Mommy would greet, but with our own little additions too.
Code:
// Inherits from Parent
-(NSString *)greet {
NSString *parentGreeting = [super greet];
return [parentGreeting stringByAppendingString:#", Mommy"]
}
So now Parent greets "Hello", and the Child greets "Hello, Mommy". Later on, if we change the parent's greet to return just "Hi", then both classes will be affected and you will have "Hi" and "Hi, Mommy".
super is used to call a method as defined by a superclass. It is used to access methods that have been overriden by subclasses so that the class can wrap its own code around a method that it's parent class implements. It's very handy if you are doing any sort of inheritance at all.