3

The talk is about classes and objects in Objective-c. I can't get my head around the concept of [super dealloc]. We have some class say myClass, that inherits from NSObject. It has some methods and inherits other methods from parent class. So we have dealloc method here too. Why can't I just use [myInstance dealloc]? Am I right to think that we call parent class method to kill the instance of the class? Why so complicated?

That's not discussion about [myInstance release] I'm ok with that concept.

Dvole
  • 5,725
  • 10
  • 54
  • 87

7 Answers7

8

There are already some good answers, but I'll answer the questions a little more directly:

  1. Why do we write [super dealloc]?

    We write it because that's what actually destroys the instance. Otherwise the memory would never be freed.

  2. Why don't we write [self dealloc]?

    We can't write that because the only place where you should ever explicitly call dealloc is inside a dealloc method. Doing [self dealloc] inside dealloc would just make the method call itself, which would then call itself, and call itself, and call itself, and call itself….

  3. Why don't we write [myInstance dealloc]?

    I assume myInstance is just a placeholder for a variable in another method that points to an object, and you're asking why we don't just call dealloc through that variable. This is because you don't know when the object should dealloc. The whole point of retain and release is to free you from having to keep track of when an object is ready to be destroyed. You just retain and release the object properly, and when release has been called enough times, signaling that the object has no more owners who want to keep a reference to it, it will call dealloc on itself.

Chuck
  • 234,037
  • 30
  • 302
  • 389
7

Your question is actually a more generic question that can be removed from the dealloc issue.

Overriding methods and when you should call super.

Sometimes when you are subclassing you override an existing method. Sometimes you want to use that convenient time to perform some behavior, sometimes you want to prevent the parent from doing something and change behavior.

- (void)methodOne {
  // don't let silly parent class do method one stuff

  // do my stuff …
}

- (void)methodTwo {
  // let parent perform his behavior first
  [super methodTwo];

  // do my stuff …
}

- (void)methodThree {
  // do my stuff …

  // let parent do his stuff after I have
  [super methodThree];
}

- (void)methodFour {
  // it's not common, but you might want to split your stuff with a call to
  // super - this usually involves knowledge of what super is up to

  // do some stuff …
  [super methodFour];
  // do my stuff …
}

The documentation for many methods/classes (see UIView and NSManagedObject) might say whether you can or should or shouldn't override methods. Good documentation will tell you when you should invoke super.

When invoking [super dealloc] you should invoke it last, after you have released the resources you have a hold on. (because it's likely that other memory you might reference will be released by your parent class).

Another oft invocation of super is in init methods. If you implement an init method, you should override the parent's "designated initializer", and you should call super from yours.

@implementation CustomViewController

- (id)init {
  return [super initWithNibName:@"CustomView" bundle:nil];
}

- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle {
  return [self init];
}

//…

This common pattern prevents anyone from loading your class with the incorrect nib file. (This may or may not be desired, that's another issue.)

If there happened to be other initializers, by definition they should invoke their designated initializer. So if UIView were to add a initWithNibName: method, it would likely invoke [self initWithNibName:name bundle:nil] which would then be "caught" and redirected to your intended initializer.

bshirley
  • 8,217
  • 1
  • 37
  • 43
5

When -dealloc is called, the contract is that it works its way up the class hierarchy to ensure the memory used by every parent class is disposed of correctly. [self dealloc] would call your method again and give you an infinite loop. [super dealloc] tears down whatever your superclass set up--and if that superclass is NSObject, it also frees the memory the object occupies.

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • Why infinite loop? I don't quite understand. Let's see. My class has some methods, let's say it got few instance variables and some methods from NSObject. I call dealloc on it from itself. It frees the memory taken by variables and methods. How come it enters infinite loop? Once the memory is clear it just stops? – Dvole Jul 05 '11 at 18:43
  • 2
    You *never* call `[self dealloc]`. *Ever*. You only call `[super dealloc]` at the end of your `-dealloc` implementation. But imagine what would happen if you called `[self dealloc]` there instead. You'd call your own code, which would call your own code, which would call your own code, which would call your own code, etc. – Jonathan Grynspan Jul 05 '11 at 18:47
  • you never invoke any `dealloc` other than calling `super` from your own implementation of `dealoc` – bshirley Jul 05 '11 at 19:03
  • @Dvole Because that's what `[self «methodName»]` always does in all of Objective-C— it calls the `«methodName»` on the current instance, using the instance's (sub-most)-class's methods _(unless that subclass doesn't implement that method, in which case it keeps look for a method of that name up the superclass chain)_.  So if you have a class with an `- methodA` method and a `- methodB`, and inside `- methodA` you call `[self methodB]`, you'll be able to see program flow into `- methodA`, then `- methodB`, then back out to finish off `- methodA`. – Slipp D. Thompson Jul 26 '18 at 13:02
  • @Dvole But if `- methodA` were to call `[self methodA]`, then you'd see the program flow into `- methodA`, then recursively into `- methodA` again _(now `- methodA` on the program stack twice)_, then again and again and again until the program stack has run out of depth and you have a stack overflow.  This works the same in C++ or C# or Java or Ruby or any other OO language— a method calling itself unconditionally with stack overflow.  `[super methodA]` in Objective-C just says _“call `methodA` on this instance of myself, but look for the method starting at the superclass, not this class”_. – Slipp D. Thompson Jul 26 '18 at 13:06
  • @Dvole So no, `[self dealloc]` doesn't have any magical ability to free any memory— it's just a plain-old method call to your own class's `- dealloc` method.  Only the root-superclass-`NSObject`'s `- dealloc` does the memory-freeing magic.  That's why you call `[super dealloc]` at the end of your `- dealloc` method, so that your class's superclass _(say your class is `MyViewController` so its superclass is `UIViewController`)_ gets a chance to do its own cleanup, then its superclass _(`UIResponder`)_ does its cleanup, and finally its superclass `NSObject` can free your instance itself. – Slipp D. Thompson Jul 26 '18 at 13:14
3

You do it like this:

@interface MyClass : SuperClass
@end

@implementation MyClass

- (void)dealloc
{
    // Release stuff allocated in MyClass
    [super dealloc];
}

@end

So what does it mean ? Suppose you've got an instance of MyClass and it has been released/autoreleased until its retain count drops to 0. Objective-C now want to destroy the instance. To clean up stuff, Objective-C calls dealloc method.

Now, what gets called is the dealloc as defined in MyClass. But you have derived the class from some other class. And that means that this superclass may have stuff to clean up as well. So you have to call [super dealloc]; which means: execute the dealloc as defined in SuperClass.

A similar concept applies to your init or initFoo methods: in it you do something like self = [super init]; so the superclass can do its initializing.

Also, you should never call dealloc directly ! It is meant to be called by Objective-C only when it's time to clean up the object.

BTW, self means: the current instance of my object, while super means: the current instance of my object, but use the methods as defined by the superclass.

DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • Yeah that part is clear, but why bother with superclass? I thought that when I inherit myClass from say NSObject it gets it's methods and variables hard-copied into myClass, for say ease of use. But is it not? So every time I call parent method it looks it up all the way to NSObject? Wouldn't it be easier if methods got just copied from superclass? And not talking about more overhead and resources. – Dvole Jul 05 '11 at 18:48
  • 2
    @Dvole: You get the *variables*, but you have to initialize and clean them up. For example, suppose you derive from `UIView`: you do not know its variables, and even if you knew them you would not know *how* to initialize them and how to clean them up. That's why it's necessary to use `[super initWithFrame:aFrame]` and `[super dealloc]`. – DarkDust Jul 05 '11 at 18:52
1

In short, it's the complement of the initializer. The concept is that the initialization propagates from the top to the bottom of the inheiritance hierarchy to initialize all parent fields first and that the deallocation propagates from the bottom to the top to clean up all the child fields first. In your init method, you always call [super init] first and in dealloc you always call [super dealloc] last. For a bit more info on [super dealloc], check out this question

Community
  • 1
  • 1
Kongress
  • 2,244
  • 3
  • 20
  • 30
0

No you are right.

The parent class (NSObject in your example) has to run its own instructions. That's why just after you wrote your release instructions, you send dealloc to the superclass in order to complete the process.

0

Using [self dealloc] in -dealloc would result in infinite recursion. The -dealloc method would just keep calling itself. You can't use [object dealloc] in -dealloc because you don't, and shouldn't, have a pointer to yourself aside from self. You are correct that NSObject needs to do its own cleaning up. Everything a class creates it is responsible for cleaning up. Also, [super dealloc] must be the last line of -dealloc. Otherwise you may not have an allocated object after that point.

rbrown
  • 2,635
  • 2
  • 24
  • 24