I'm facing a bit of a confusion involving weak and strong properties. For the sake of brevity I won't include the entire code.
I created a class convenience method which returns a UIView object, and I implemented it in a UIView category as an alternative to subclassing.
@implementation UIView (CSMonthView)
+ (UIView *)monthViewFromDateArray:(NSArray *)arrayOfAllShiftsAndEvents withNibOwner:(id)owner selectedDate:(NSDate *)selectedDate withCompletionHandler:(void(^)(CSCalendarButton *selectedButton))block
{ // .. do some stuff
// Create an instance of UIView
UIView *monthView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320.0, 200.0)];
// Create UIButtons and set the passed down 'owner' value, as the target for an
// action event.
// Add UIButton as subviews to monthView....
return monthView;
}
I should note that inside the method I do not have anything pointing to monthView.
Now inside the implementation of the 'owner', which is a class called CSCalendarViewController, I create the above UIView by calling the class convenience method and assign it to a UIView property called _monthView.
@interface CSCalendarViewController : UIViewController
@property (weak, nonatomic) UIView *monthView;
@end
@implementation CSCalendarViewController
__weak CSCalendarViewController *capturedSelf = self;
// Create the current month buttons and populate with values.
_monthView = [UIView monthViewFromDateArray:_arrayOfAllShiftsAndEvents withNibOwner:self selectedDate:_selectedDate withCompletionHandler:^(CSCalendarButton *selectedButton) {
capturedSelf.selectedButton = selectedButton;
[capturedSelf.selectedButton setSelected:YES];
}
Now my confusion is this. Even though I defined the property 'monthView' as weak, 'monthView' still holds on to the value of the returned UIView.
If I go ahead and do something like this:
_monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];
The compiler gives a warning (as it should) saying "Assigned retained object to weak variable".
Why am I not getting the same error message when I assign 'monthView' to the UIView that returns from the class method?
I don't have a deep understanding when it comes to pre-ARC memory management, and I think I'm missing something obvious. Thanks.
Say we have method
It is converted to this when compiled
Now here:
The first line is converted to this:
The second line:
If we have the code like this:
You can see all of this by looking at code disassembly.
It won't for long. This question demonstrates the underlying workings of ARC, and how it is a translation to the traditional retain/release methods, rather than a whole new memory management system.
Pre ARC
Before ARC, there was no concept of weak or strong, instead it referred to retain and assign. Assigning to variables did nothing to the reference count, it was up to the developer to manage it.
Now, in regards to the memory management policies, a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”, will return a retained object (Documentation). This meant, on assignment to a variable, the developer didn't need to explicitly retain (they had to explicitly release, or autorelease):
Methods that don't have that naming convention, suggest they return an autoreleased object. The developer needs to say something explicitly, to keep the object around longer:
ARC + MRC
ARC removes this unnecessary need of releasing and retaining, and instead decides what to do with the memory management based on the type of variable it will be assigned to. This doesn't mean the memory management model changed; it is still all retain and release under the hood. As such, how does this affect you? For brevity, this answer will only take into account weak variables.
Assigning to a weak variable does not do anything with the retain count of the object. Lets see a practical example to explain:
Because (in reality, behind the ARCness) this is returning a retained object, but weak variables don't affect the retain count, the compiler has found the earliest point to release the object in order to prevent a memory leak; on allocation! As such, it will be translated to the following, and cause an error:
Now, in regards to
monthViewFromDateArray:
, this is suggesting to the compiler (due to its name), that it will return an autoreleased object (Documentation). Because the compiler is aware that an autoreleased object will be released automatically later on in the run loop (when the autorelease pool is drained), it will not insert arelease
call like before. As such, the assignment to a weak variable isn't an issue, but it's only really valid within the scope it's being used in.