Object leak using "retain" - iphone

I have a property defined with retain attribute which I am synthesizing:
#property (nonatomic, retain) UISwitch *mySwitch;
And inside my loadView I am doing this:
self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
And finally inside my dealloc I am doing this:
self.mySwitch = nil;
Am I leaking this object (mySwitch) as I have used one alloc? Should I autorelease it while assigning it frame?
Please suggest.

The line:
self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
Actually calls retain twice- once for the alloc and again in the assignment to self.mySwitch (which is a property you've specified should retain any values assigned to it.) The fix I have been told is best is to add a call to autorelease on the line, making it:
self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];

Yes, you are leaking. You are creating an owned object with +alloc/-initWithFrame:, then assigning that owned object to a property marked retain. This creates a second owned reference to the object. At this point, you leak your original owned reference, which causes the object itself to leak.
The correct behavior here is to call -autorelease on the object before assigning it to the property.
self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];
On a tangential note, it's not recommended that you access properties inside of -dealloc. The two reasons generally given for this are 1) this will broadcast KVO notifications, which you don't want inside of -dealloc, and 2) if anyone overrides the setter (in this class or a subclass) it may not behave properly. The recommended approach is to simply release the underlying ivar, so you'd see something like the following instead:
[mySwitch release];
Assigning nil to the property is perfectly safe (and recommended) everywhere else.

As alternative to autorelease, if you need a tighter memory management this should work for you:
UISwitch *myswitch_tmp= [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
self.mySwitch = myswitch_tmp;
[myswitch_tmp release];
and later e.g. in dealloc
[mySwitch release];

Yes. You are leaking object. Remember one simple rule here:
if you used +alloc there is always must be corresponding -release.

Related

objective c class method returned value, assigned to weak/strong properties

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.
'monthView' still holds on to the value of the returned UIView.
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):
// Will have a retain count of 1 here
var = [NSString alloc] initWithString:#"Test"];
// Will have a retain count of 2 here
var = [[NSString alloc] initWithString:#"Test"] retain]
// Will have a retain count of 1 here, but will be released later on automatically
var = [[NSString alloc] initWithString:#"Test"] autorelease];
// Will have a retain count of 0 here, and will be released before it reaches the variable!
var = [[NSString alloc] initWithString:#"Test"] release];
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:
// Will have a retain count of 1 here, but will be released later on automatically
var = [NSString stringWithString:#"Test"];
// Will have a retain count of 1 here
var = [[NSString alloc] initWithString:#"Test"] retain]
// Will have a retain count of 1 here, but will be released twice later on (Over-released!)
var = [[NSString alloc] initWithString:#"Test"] autorelease];
// Will have a retain count of 0 here, and will be released again later on (Over-released!)
var = [[NSString stringWithString:#"Test"] release];
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:
__weak UIView* monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];
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:
UIView* monthView = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)] release];
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 a release 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.
Say we have method
+(UIView*) create {
return [[UIView alloc] init];
}
It is converted to this when compiled
+(UIView*) create {
return [[[UIView alloc] init] autorelease];
}
Now here:
UIView* __weak view;
//warning here
view = [[UIView alloc] init]; //1
view = [AppDelegate create]; //2
The first line is converted to this:
tempVar = [[UIView alloc] init];
storeWeak(tempVar, &view); //view = tempVar and marked as weak
[view release]; //view is nil after this because retain count == 0 (assignment to nil is done in release internally)
The second line:
tempVar = [MyClass create];
[tempVar retainAutoreleasedReturnValue];
storeWeak(tempVar, &view); //view = tempVar and marked as weak
[release tempVar]; //view is not nil because tempVar is autoreleased later
If we have the code like this:
#autoreleasepool {
view = [[UIView alloc] init];
//view is nil here
view = [AppDelegate create];
//view equals to the return value
}
//view becomes nil here because [AppDelegate create] return value is released
You can see all of this by looking at code disassembly.

Sending messages to released objects?

I have several UIView subclasses (buttons, labels, etc.) that follow the following setup pattern. My question is, why are messages still able to be sent to the UILabel after release?
myLabel = [[UILabel alloc] initWithFrame:someFrame];
[someUIView addSubview:myLabel];
[myLabel release];
myLabel.textAlignment = UITextAlignmentCenter;
// other property changes to myLabel
They are "owned" by a new UIView, I suppose, but I don't understand why release doesn't destroy the original object and thereby all messages to it. I'm not making property changes through someUIView's subViews. I'm not complaining. I'm just trying to understand why.
EDIT: I should add that these are instance variables, if that makes a difference.
The object is not destroyed as long as the retain count is greater than 0. In this case someUIView has retained the object.
It is really best not to access an object after releasing it. a better pattern might be:
myLabel = [[[UILabel alloc] initWithFrame:someFrame] autorelease];
myLabel.textAlignment = UITextAlignmentCenter;
[someUIView addSubview:myLabel];
myLabel = nil;
Second example:
myLabel = [[UILabel alloc] initWithFrame:someFrame];
[someUIView addSubview:myLabel];
myLabel.textAlignment = UITextAlignmentCenter;
// other property changes to myLabel
[myLabel release];
myLabel = nil;
Your call to -addSubview: calls -retain on the label when it receives it. At this point, you relinquish ownership (by calling -release) and only the view owns it. But it still exists until the containing view also releases it.
You can still send messages to the label because the label hasn't been released yet. -addSubview: retains the objects passed in, so the object remains in memory since the view is still holding a reference and you didn't nil the myLabel pointer.
Because they are probably retained before...

Self syntax in iPhone development

What is the difference between the following two approaches for the self syntax to access the object properties:-
Approach 1:-
self.effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
self.effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
Approach 2:-
effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
effortView is defined as a property, and synthesized, to the Class addressed as self in Approach 1. Both of the approaches work.
I am using Xcode 4.0 iPhone SDK 4.3 on Mac 10.6.6.
Please enlighten me.
Thank you All
In the first syntax:
self.effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
self.effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
you are accessing both ivars through their accessor methods (usually, effortView to get, setEffortView to set).
In the second syntax:
effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
you are accessing the effortView ivar directly (pointer assignment), while you are accessing effortTableView through its property accessor.
The difference is that using an accessor you obtain additional behavior. Like, with the standard set accessors generated by the #synthesize keyword for a retain property:
#property (nonatomic, retain) NSObject* property;
you get automatic retain count management (i.e., retain count will be automatically incremented on the assigned object; if the ivar had already a value, the object pointed to will have its retain count decreased). What this implies is that in your first example, you are causing 2 memory leaks. Indeed, (if the properties are declared as retain property) assigning to them will increase their retain count; but [[alloc] init] already gives back an object with a retain count of 1, so you don't need to increment it once more. Correct would be:
self.effortView = [[[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
self.effortView.effortTableView = [[[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped] autorelease];
Overall, properties make much easier to deal with retain count management and are the suggested way to go with it, but you have to be aware of their "retain count" semantics and account for that.
I would suggest this article as an interesting reading.
If the property is declared like this
#property (nonatomic, assign) EffortView *effortView;
both approaches are equivalent. In the case the property is declared like this
#property (nonatomic, retain) EffortView *effortView;
the code [[EffortView alloc] init...]; first generates a retained EffortView instance and then the 'assignment' self.effortView = ... retains this instance again. Therefore to balance the retain count you have to release the generated instance.
The former uses the accessors methods generated by the synthesize statement.
The latter accesses the variable directly.
self.effortView uses the accessor methods generated by #synthesize to get and set the property, while effortView accesses the instance variable directly. Inside the class where the property is defined, the difference is most important when considering the setter: it automatically takes care of memory management. So if you've done this:
#property (nonatomic, retain) EffortView *effortView;
then the two approaches have different results. Approach 1 leaks in this case, as the setter retains the object and you +alloc it without a balanced -release.

Dealloc method of UIView subclass not getting called

I have a view controller named SettingsViewController, and a custom UIView subclass named ViewAccounts. In SettingsViewController, I am using the code below to add ViewAccounts view into SettingsViewController.
if(!self.viewAccounts)
{
ViewAccounts *objViewAccounts= [[ViewAccounts alloc] initWithFrame:CGRectMake(0, yViews, 320, 400) withViewController:self];
[self.view insertSubview:objViewAccounts atIndex:0];
self.viewAccounts = objViewAccounts;
[objViewAccounts release];
}
The Problem is that the dealloc method of ViewAccounts (subclass of UIView) is not getting called. If I comment these both lines of code, then dealloc method gets called.
[self.view insertSubview:objViewAccounts atIndex:0];
self.viewAccounts = objViewAccounts;
I guess the problem is with retain count, at it gets incremented by 1 when we use insertSubview or addSubiew, but how to get rid of it. Is this the right approach to use it?
Just as a note: making viewAccount to assign can cause a Zombie down the road (in the original code snippet) because you release it in the last line.
I would suggest the following approach:
Make viewAccounts retain again
Don't use autorelease because you are not returning it from that method
Pay attention to dealloc method of the method in the snippet
This is how I would write the snippet with viewAccounts retaining
if(!self.viewAccounts)
{
ViewAccounts *objViewAccounts= [[ViewAccounts alloc] initWithFrame:CGRectMake(0, yViews, 320, 400) withViewController:self];
[self.view addSubview:objViewAccounts];
self.viewAccounts = objViewAccounts;
[objViewAccounts release];
}
...
- (void) dealloc {
[super dealloc];
[viewAccounts release];
...
}
What happened in your original code was that the retaining variable viewAccounts was not released properly at the end of the this class life cycle and so dealloc was not called.
BTW when you only assign the variable then you have to manage the retain yourself if you re-assign that variable especially if you NIL it. Assume that you set the variable to NIL then the snippet could be executed again. But then you overwrite the variable and you are not able to release the first value. If you use retain the Object-C will do that for you. As a rule of thumb I would always use retain for properties until you have enough experience to handle the other cases.
You could set your objViewAccounts to autorelease, since it will be retained by self.view anyway.
ViewAccounts *objViewAccounts= [[[ViewAccounts alloc] initWithFrame:CGRectMake(0, yViews, 320, 400) withViewController:self] autorelease];
Also regarding the retain count, if the property self.viewAccounts is declared as retain, that would also increase the retain count by 1.

(iphone) basic memory management question

I have used following 2 patterns to create a view.
#property (retain, nonatomic) SomeView* someView;
...
// First pattern
self.someView = [[SomeView alloc] initWithFrame frame];
// Second pattern
SomeView* aSomeView = [[SomeView alloc] initWithFrame];
self.someView = aSomeView;
[aSomeView release];
Now, looking back at this code, the first pattern's method should be changed to
self.someView = [[[SomeView alloc] initWithFrame frame] autorelease];
shouldn't it?
I feel dumb :(
Look at it like this:
[[SomeView alloc] initWithFrame: frame];
The above line creates an object and gives it a retain count of 1.
self.someView = [[SomeView alloc] initWithFrame: frame];
This line leaves it with a retain count of two, because the someView property is declared with retain:
#property (**retain**, nonatomic) SomeView* someView;
So, doing it this way leaves your someView property pointing to an object with retain count of 2. You can do it this way if you add an autorelease call to it:
self.someView = [[[SomeView alloc] initWithFrame: frame] autorelease];
Your second pattern is better, if you ask me. You create an object with a retain count of one. You assign it to a retaining property (now it has a retain count of 2) and then you release the original variable, leaving the object again with a retain count of 1. It's three lines where you might want only one, but it makes sense in the right context. Additionally, it's usually best to avoid using autorelease outside of an alloc or copy method since its usually an indication you don't fully understand memory management in Obj-C.
And as a commenter said in the comments to the question, don't feel dumb. None of this is intuitive at first. Nobody picks up a guitar and plays like Hendrix their first time.
Yes, you are right. autorelease means "release a bit later".
Yes, I think you should change that. With self.someView = you are calling the setter which increases the retain count.
Now, looking back at this code, 1's method should be changed to self.someView = [[[SomeView alloc] initWithFrame frame] autorelease];
shouldn't it?
correct
a)
SomeView * view = [[SomeView alloc] initWithFrame:frame];
self.someView = view;
[view release], view = nil;
b)
self.someView = [[[SomeView alloc] initWithFrame:frame] autorelease];
many people prefer b, simply because it is less to type.
i prefer an approach similar to a because:
defects (such as over-releasing) are often exposed near the call site, rather than when the pool is destroyed (this often means you have to load up Instruments in Zombie mode to locate the callsite)
it performs better and minimizes memory usage (in general, but not much in this specific case)
you have more opportunity to check for invalid states and results
you have a chance to init/configure the view/object for its usage before adding it to self, which is usually preferred