Search code examples
objective-cpointersmemory-managementself

memory/pointer behavior for self = [super init]


Forgiveness, please: I am a beginner. I was looking at another quesiton/answer and came across this code:

SpinningView *spinner = [[SpinningView alloc] initWithFrame:CGRectMake(0.0, 0.0, 20.0, 20.0)]

// Now let's take a look at the implementation of SpinningView's -initWithFrame: method

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self)
    {
        self.backgroundColor = [UIColor clearColor];
    }

    return self;
}

I believe that, in the second section of code, self points to the instance to which the message was sent that resulted in "self" being encountered, i.e., the result of [SpinningView alloc]. (Or doesn't that produce an instance?)

So, when you call self = [super initWithFrame:frame] on the 4th line of code, are you not reassigning the pointer value associated with "spinner"? I.e, are you not abandoning the memory you allocated in the first line? Or does the compiler someone know just to copy memory values instead of changing the pointer value? Or... what??

Thanks!


Solution

  • @KevinBallard covered most of the points. The reason we need the self = is because init is not guaranteed to return the same object it is called on (it could return a different object or nil). I will answer your questions and expand on the memory management aspects:

    I believe that, in the second section of code, self points to the instance to which the message was sent that resulted in "self" being encountered, i.e., the result of [SpinningView alloc].

    Yes

    So, when you call self = [super initWithFrame:frame] on the 4th line of code, are you not reassigning the pointer value associated with "spinner"?

    Yes. Not spinner (spinner doesn't exist at this point anyway). You are re-assigning the pointer variableself inside the method.

    I.e, are you not abandoning the memory you allocated in the first line? Or does the compiler someone know just to copy memory values instead of changing the pointer value? Or... what??

    Yes. Under MRC, you are just re-assigning the pointer, and the compiler does not do anything except change the pointer value. Under ARC, it's more complicated, but at the end of the day, the compiler just does the same as under MRC in this case, i.e. just re-assigns the pointer.

    It's not really "abandoning" the memory if you think about it. You see, by convention, init methods take ownership of ("consume") an already-retained object that they're called on (usually the return result of a call to alloc), and they return a retained object. But these two don't have to be the same object. So when your init method is called, its self is already retained, and the init method owns it, but then it calls [super init...], which calls the superclass's init method on self, so that method now takes ownership of the self which your init had ownership to. And in return, that superclass's init returns back to you a retained instance, which you assign to self. You did not "abandon" self because you gave it to the superclass's init method, which in turn became responsible for memory managing it (including releasing it if it wants to return something else).