i have created multiple insances in my h file
IBOutlet UIImageView *imageView;
IBOutlet UIImageView *subImageView;
IBOutlet UIImageView *arrowRight;
IBOutlet UIImageView *arrowLeft;
IBOutlet UIImageView *arrowDown;
My project is in the ARC mode
do i have to set them to nil in dealloc () method inorder to release them??
Thanks
If you don't need the global instances after one of your objects is deallocated, the best way would be to set the global pointers to nil in dealloc.
- (void)dealloc {
gYourGlobalPointer = nil;
}
Note that in ARC you can't call [super dealloc], dealloc will be sent to your superclass automatically.
you can make them nil in viewDidUnload as following:
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
self.myOutlet = nil;
}
in ARC you don't have to worry about releasing instance veritable of a property at all. Compiler will take care of them for you.
If you want to release manually you have to assign nil to all strong variables pointing to particular instance.
Related
I have literally 24 IBOutlets in one view of a NavigationController (none are retained as properties). Is there a good way to release these? I have a feeling they are causing memory issues in slower 3G and 3GS devices.
No ARC
Any thoughts?
As you push UIViewControllers on to a UINavigationController, the view of the UIViewControllers which have been "pushed onto" may be unloaded to save memory (as they are invisible). The views are then reloaded when necessary (and you get the viewDidLoad callback). You should have IBOutlets to UIViewControllers not UINavigationController so that they can be released on viewDidUnload. The usual way to release them is to declare them as retained properties and set them to nil (with the self.outlet accessor) in viewDidUnload and dealloc. Or just use ARC.
ViewController.h
#interface ViewController : UIViewController
{
}
#property (retain, nonatomic) IBOutlet UILabel *myLabel;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize myLabel;
#pragma mark - View lifecycle
- (void)viewDidUnload
{
[self setMyLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[myLabel release];
[super dealloc];
}
#end
1- Is these anything wrong with the way
i am deallocing the object?
2- Does my dealloc override the dealloc
for NSManagedObject?
3- Do i need to dealloc super even
though my object is an
NSManagedObject type and core data ia
responsible for it?
#interface MyClass : NSManagedObject
#property (nonatomic, retain) NSString *coreDataString;
#property (nonatomic, retain) NSNumber *coreDataNumber;
#property (nonatomic, retain) CoolObject *coolObject;
#end
.
#implementation MyClass
#dynamic coreDataString;
#dynamic coreDataNumber;
#synthesize coolObject;
- (void)dealloc
{
[self.coolObject release];
}
#end
Yes, you are not calling [super dealloc].
Yes.
Yes, you must always call [super dealloc] at the end of your dealloc method. Otherwise memory will not be freed correctly.
You should call release on the member variable directly instead of using the property. You also should still call the super dealloc. So your dealloc would look like this:
- (void)dealloc
{
[coolObject release];
coolObject = nil;
[super dealloc];
}
Otherwise, you can set the property to nil which will automatically release the local variable if necessary. The above way is preferred so you don't accidentally run a complicated function that could be overriding the property's setter.
You should always call [super dealloc] in the dealloc method. But in subclasses of NSManagedObject you should never use the dealloc method at all. use - (void)didTurnIntoFault instead.
You are overriding the parents - (void)dealloc method. When you override a parent object's method, the parent's method is never called until you explicitly call the super's method. In your case, the parent's - (void)dealloc is not called. To fix this, you must call [super dealloc] to ensure that the parent's instance variables are deallocated too.
I have been working on an app, and the book I read said to put these statements into the viewDidUnload and dealloc methods. What other information should go here? I have buttons and labels in my program. Do I need to do anything for them?
I want an efficiently running application.
Here's my code:
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.doublePicker = nil;
self.color = nil;
self.choice = nil;
[super viewDidUnload];
}
- (void)dealloc {
[doublePicker release];
[color release];
[choice release];
[super dealloc];
}
You should only release your IBOutlets and other UI elements in viewDidUnload. All the other data that you allocated in your view controller (as well as the IBOutlets) should be released in the dealloc method. That's because the view can be loaded and unloaded multiple times during the lifetime of a view controller. For example, a view can be unloaded if it is not visible, but the data behind it (in the view controller) still needs to be kept in memory. When both the view and its controller are no longer needed, the dealloc method is called.
The code you posted is correct, but you should also create properties for your outlets, like so:
in your .h file:
#property (nonatomic, retain) UIPickerView *doublePicker;
#property (nonatomic, retain) UIPickerView *color;
// ...etc
in your .m file:
#synthesize doublePicker;
#synthesize color;
// ...etc
There is some debate about this technique (explicitly retaining your outlets and releasing them like this), but it is the technique that Apple recommends:
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmNibObjects.html#//apple_ref/doc/uid/TP40004998-SW2
The general rule is that you want to call release on anything that you alloc or init. Components that you create in xib's do not need to be released.
I'm still a little confused on this.
I'm creating an object programmatically in Xcode, let's say a UILabel, which is also going to be a class wide property.
When is the proper time to release the object, in the method in which it is created, or in the dealloc method like normal IBOutlet objects?
Thanks.
This depends on whether your property is set to retain the value or not. Usually you want the accessors (generated by #synthesize) to handle the retain/release when the property is set to a new value. You specify such a property like this:
MyController.h
#interface MyController : UIViewController {
UILabel *myLabel;
}
#property (nonatomic, retain) UILabel *myLabel;
#end
You can then use #synthesize to generate the default getters and setters. The default setter for a 'retain' property will release the current value and retain the new value. However, nothing is done for you in dealloc. Meaning, that when the controller is destroyed, your reference to you label will leak since release will not be called. For this reason, you need call release on all your 'retain' properties in dealloc, like this:
MyController.m
#implementation MyController
#synthesize myLabel;
-(void) dealloc {
self.myLabel = nil;
[super dealloc];
}
#end
Notice that in this case, self.myLabel = nil is almost equivalent to calling [myLabel release] since the setter will call release on the existing value and then call retain on the new value. Since the new value is nil, calling [nil retain] has no effect. I prefer to nil instead of releasing since you are also setting the ivar to nil and avoids dangling pointers.
When you create a property like this programmatically as opposed to from Interface Builder, you don't need to mark it with IBOutlet. In the cases where you do create a control using IB, you should nil all of your IBOutlet references in viewDidUnload. This is because your control could be deallocated along with the view if it wasn't retained. Referencing it afterwards will crash the app so it's a good practice to nil them, like this:
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.myIBLabel = nil;
}
Another common mistake that happens when using properties is to omit the 'self' part. If you do not use the self.myIBLabel notation, you are bipassing the getter and setter and working with the ivar directly. This will NOT retain/release the object.
You should release it in the dealloc method, although that depends how you're creating your class property.
If you release it in the method in which you create it, and then use it in some other part of your class (which, since you're making the UILabel a class wide property, I assume you are), you will get a bad access when you try to modify it later on. Note that if you're using a retained property you need to take that into account, in which case you might release the label (because you'll have created it and assigned it to your class property, which will retain it again).
Here's a typical example:
- (void) someMethod {
UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];
self.textLabel = myLabel;
[myLabel release];
}
- (void) dealloc {
[textLabel release];
}
I've defined a view controller with an array as one of its properties, and set the array with an allocated and autoreleased array.
After I push the view for display I release it.
By watching the leaks tool I see that every time that I pop the view I suffer from leakage.
I tried to release the properties explicitly, immediately after the push but the app crashes.
looking forward for your suggestions.
The leak is probably because of the array property is set to retain, like so:
#property (nonatomic, retain) NSArray *yourArray;
Your autorelease object is retained on assignment to the yourArray property. Since it is retained, you have to release it in the controller's dealloc method:
- (void) dealloc {
[yourArray release], yourArray = nil;
[super dealloc];
}
HTH.