To the first question:
Let's have a closer look to it:
self.subview = [[UIView alloc] init];
[UIView alloc]
returns an instance with ownership +1. This is assigned to a (non-visible) strong reference, which build the self
of -init
. -init
passes the ownership through. (This is not correct, if -init
returns an instance which is not the original receiver, but for your case it is enough details.) So we can think of the return value of -init
as an ownership transfer, too.
You assign this instance to a weak variable. In this moment it can be released. (Read: ARC does not promise to do it immediately, IIRC.) the instance variable can be nil
before the object is hold by its superview. So this code is dangerous:
self.subview = [[UIView alloc] init];
// _subview can be nil'ed
[self.view addSubView: self.subview]; // add nil
I do not believe that this is your problem, but it can be a problem. – Thinking again about it, it is your problem. Read the edit at the end. –To get rid of it, simply use a strong local variable:
UIView *subview = [[UIView alloc] init]; // defaults to __strong
[self.view addSubView: subview]; // adds an ownership
self.subview = subview;
The second question:
I do not know, why the compiler gives you no warning in the second case. What does happen, if you repair the first case?
At runtime a different handling of both cases is possible, because it is undefined, when the first instance is released. Maybe as a part of optimization a pointer is reused. More detailed:
__strong id completlyHiddenCompilerGeneratedVar;
… = [(completlyHiddenCompilerGeneratedVar=[UIView alloc]) init];
… = [(completlyHiddenCompilerGeneratedVar=[UILabel alloc]) init];
The first instance would be dealloc'ed, when the second instance is created, because it overwrites the internal strong reference.
Again: Repair the first case and tell us, what happens with the second one.