问题
When you use Xcode's feature and drag from the nib file into the .h and .m file, Xcode adds the code in the dealloc
and viewDidUnload
. It adds extra code I do not normally add. I am just curious if this extra code is needed.
I would have done [self setDisplaySlider:nil]
and not disp = nil
and [disp release]
.
Is this necessary? I don't think you have to release disp.
@interface ViewController : UIViewController
{
IBOutlet UISegmentedControl *disp;
}
@property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider;
@end
- (void)viewDidUnload
{
[self setDisplaySlider:nil];
[disp release];
disp = nil;
[super viewDidUnload];
}
- (void)dealloc {
[displaySlider release];
[disp release];
[super dealloc];
}
回答1:
In my opinion you provided a class with extra code. I'll try to explain.
First of all, in your previous you have two different IBOutlet
. I think that the first one has been added by you.
IBOutlet UISegmentedControl *disp;
The second one, instead, has been added by Xcode when you made the drag and drop oeration.
@property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider;
First consideration
The term IBOutlet
is only a placeholder for Xcode. By means of it, Xcode helps you to connect an instance variable to a graphical element.
When I use outlet connections I usually supplying an accessor like @property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider;
(as Xcode did) because if not you could incurr in memory leak problems.
Second consideration
The code Xcode has provided is right. When you made the drag operation you linked toghether displayController
instance variable with your graphical element. To balance this connection, that instance variable has to be released in dealloc method like the following:
[displayController release];
In addiction, Xcode added [self setDisplaySlider:nil];
because in memory warning situations viewDidUnload
method could be called. No problem here because whene the controller is loaded in memory again, the outlet connection is restored.
The difference between the two method calls can be read in Advanced Memory Management doc and release-or-set-to-nil-retained-members. Note that if you do this:
[displayController release];
you access directly your instance variable called displayController
, while if you do this:
[self setDisplaySlider:nil]; // or self.displaySlider = nil;
you access the accessor (the setter method in this case) for that instance variable. It's not the same (to avoid confusion see the code I provided).
So, this is the code I would use (I added some comments to guide you):
//.h
@interface ViewController : UIViewController
{
UISegmentedControl *disp; // instance variable called disp
// (A) now this is no longer necessary, new compile mechanism will create an instance
// variable called _displaySlider under the hood
}
@property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider;
@end
//.m
@synthesize displaySlider = disp; // I say to Xcode to create a setter and a getter to access the instance variable called disp as written in @property directive
// no longer necessary for (A)
- (void)viewDidUnload
{
[super viewDidUnload];
[self setDisplaySlider:nil]; // I call the setter method to release the UISegmentedControl
}
- (void)dealloc {
[disp release]; // I release the UISegmentedControl directly
// if you choose the (A) mechanism simply do
// [_displaySlider release];
[super dealloc];
}
Hope it helps.
回答2:
Have a look at your viewDidLoad:
I think you'll find that the objects are being allocated there.
You need to balance this with releases in viewDidUnload, otherwise if the view gets loaded again, the objects will be allocated again without having been released, and you'll be leaking.
来源:https://stackoverflow.com/questions/9055926/ios-memory-management-issue