I have a view controller that was presented using
[self presentModalViewController:myVC animated:YES];
this VC has several declared retained properties (#property) that I have to release on its dealloc.
The variables are declared as
#property (nonatomic,retain) myClass1 *myProperty;
#property (nonatomic,retain) myClass2 *myProperty2;
// etc... and then synthesized on .m
The problem is that when I dismiss the viewController using
[self dismissModalViewControllerAnimated:YES];
it crashes on the dealloc, when releasing the retained properties I have declared, with the error *modifying layer that is being finalized *
Apparently the the viewController is gone at the time its own dealloc runs and then it crashes.
How do I solve that? Thanks in advance.
edit
the code that presents the viewController is on the rootViewController and is this:
UIViewController *myVC = [[UIViewController alloc] init];
myVC.delegate = self;
UINavigationController *navigator = [[UINavigationController alloc] initWithRootViewController:myVC];
[self presentModalViewController:navigator animated:YES];
[navigator release];
[myVC release];
and this is the what the dealloc code on myVC contains
- (void) dealloc {
[myProperty1 release]; // see this properties at the beginning of this question
[myProperty1 release]; // if I comment these 2 relesases it stops crashing
[super dealloc];
}
myVC is dismissed from inside itself, but that's fine according to the docs. I have also tried to dismiss it from the rootviewController but it continues to crash. The only way to stop crashing is to disable the release lines on the dealloc.
How do you set the properties?
self.myProperty =
? My guess is that you do not retain them. Are you doing
myProperty = ...
by any chance, with neither a retain or self.? The setter you synthesize needs a chance to actually retain your newly created object...
So in full it should read something like this:
MyClass1 *aProperty = [[MyClass1 alloc] init];
self.myProperty1 = aProperty;
[aProperty release];
...i asked where you allocate and init "myProperty1" and "myProperty2"...
i'm afraid that you make confusion thinking that this:
#property (nonatomic,retain) myClass1 *myProperty;
#property (nonatomic,retain) myClass2 *myProperty2;
need that you release myProperty and myProperty2
well, you are wrong!
you are just declaring the kind of objects you are going to use, not allocating them
you need to release them just if you alloc them someWhere...
Related
I have a UILabel in my class header file defined as :
`#property (nonatomic, retain) UILabel *label1;`
and it exists as instance variable like this:
`UILabel *label1;`
and synthesized in the .m file, however, in viewDidLoad method I do:
`label1 = [UILabel alloc] init] autorelease];`
then I do various things on the label like setting its frame, text color, etc ...
when the view controller is deallocated, the app crashes with this message in console
(Zombies enabled): `[CALayer release] message sent to deallocated instance` ...
The app will not crash when I :
1) remove the autorelease word .. or
2) if i do not release label1 in the dealloc method .. or
3) remove [super dealloc]; from the dealloc method of the view controller.
how can I properly release this UILabel without facing such crash !!
You are doing right.Autorelease and release in dealloc.
But it shouldn't be crash.Because I did the same thing to check.
Could you please check accciendlty may be u release the label some where else.
And releasing in dealloc again.
since you have declared the label as retain. The allocation can be
UILabel *myLabel = [[UILabel alloc] init];
// set all properties of label
self.label1 = myLabel;
[myLabel release];
myLabel = nil;
And in dealloc release your label1.
[label1 release];
this is the way I'm used to and this makes things smoother for me.
the label is released already before dealloc is called. that is because its an autorelease object. your dealloc is trying to release a UIlabel that already been released, an it crashes.. in your question. you can use 1 or 2. if you allocated the object once, then call a release just once. its not because you assign retain to your property in #property directive will add 1 retain count to your object , #property(retain) will not allocate anything, but will tell the compiler how you want your properties treated
strangely enough, when I used self.label1 = [[[UILabel alloc] init]autorelease]; instead of label1 = [[[UILabel alloc] init] autorelease]; solved the problem. the dealloc method remains as is without any change. really weird !!
Do this and u will not use autorelease for label1:
- (void)dealloc
{
if(label1)
{
label1 = nil;
[label1 release];
}
[super dealloc];
}
I have some problem with my singleton and UIViewController there;
Singleton.h
#property (nonatomic, retain) UIViewController *viewController;
Singleton.m
...
#synthesize viewController = _viewController;
- (void)load {
self.viewController = [[[UIViewController alloc] initWithNibName:#"NibName" bundle: nil] autorelease];
}
- (void)unload {
[_viewController release];
}
This viewController using by different part of the application via pushViewController:animated:. But sometimes I need to release viewController by calling method - (void)unload of Singleton class! If pushViewController:animated: never call for viewController everything is well and dealloc is calling, but if pushViewController(and viewController perform viewDidLoad), dealloc isn't work. If I do something like self.viewController = nil; dealloc calling twice... What I'm doing wrong???
Your unload function should only consist of:
- (void)unload {
self.viewController = nil;
}
When you set a retained property to nil, it releases the instance variable AND nils it. You are simply leaving a dangling pointer on your property here.
You need to set it to nil after releasing it:
[_viewController release];
_viewController = nil;
Otherwise the next person who comes along will try to do stuff with an invalid pointer.
I'm working on a nvaigation-based application and I want to use "global variables" in it.
I used the AppDelegate class, in each view I want to access the variables with I do like the following:
.h
#interface Main : UIViewController{
iMEAppDelegate *datacenter;
}
#property (nonatomc, retain) iMEAppDelegate *datacenter;
#end
.m
#synthesize dataCenter;
-(void)viewDidLoad{
[super viewDidLoad];
dataCenter = (iMEAppDelegate *)[[UIApplication sharedApplication] delegate];
}
Now the first time the view appears it's working fine but when navigating to another
one and return back and repress the button that has the below code, the EXC_BAD_ACCESS error is thrown:
if ([dataCenter.userName isEqualToString:#""]){
SingIn *obj = [[SingIn alloc] initwithNimName:#"SingIn" bundle:nil];
[dataCenter.navController pushViewController:obj animated:YES];
[obj release];
I'm not sure why is this happening, I'm thinking it may be a memory management issue but I couldn't find a solution to it.
Please help.
From the code you provided, my guess for the reason of your EXC_BAD_ACCESS is that you have forgotten to retain your AppDelegate's properties, e.g. dataCenter.userName.
First thing i do is create a ViewController and push it to the Navigation Controller.
viewController = [[MyViewController alloc] init];
[navController pushViewController:viewController animated: NO];
[viewController release];
Retain count is 2 now (pushViewController uses 2 retain apparently but not my responsibility) so far so fine.
Inside MyViewController i'm createing a instance of a class and sets the ViewController as delegate to the instance.
timer = [[MyBackgroundTimer alloc] initWithInterval:20];
[timer setDelegate:self];
Now the viewControllers retain count has increased by 1 becouse of setDelegate:
But when i'm releasing the viewController later it will never call dealloc becouse i have one more retain count.
How should you correctly drop the retain count when you set your self as delegate?
Don't retain your delegate. If you're using a property, define your delegate as assign, not retain. Somebody else needs to retain your delegate, not you.
Your class MyBackgroundTimer should have the delegate property as assign and not retain.
#property (nonatomic, assing) id delegate;
And this class should retain the delegate just when it needs to use it, and release when it is done.
#implementation MyBackgroundTimer
#synthesize delegate;
-(void) startTimer {
[self.delegate retain];
//... do some actions
}
-(void) timerStopped {
//... call delegate methods
[self.delegate release]
}
#end
It is important to remember that you can have your delegate as a retain property. But to do so the right way, you have to ensure that you release it before dealloc is called (like the timerStopped method in the example above)
I say that because if you try to release the delegate at the dealloc method, the class that instantiates MyBackgroundTimer is the same class as the delegate, and it also releases MyBackgroundTimer at the dealloc (which is pretty much the common case), the dealloc method of both classes will never be called, as each class will have the ownership of the other, resulting in a memory leak (that will not be shown at instruments).
I have a view controller. The view controller has a retained object called streamController, which is an NSObject subclass that handles all of the data I/O with my server. All is well, except I'm trying to figure out why some things are leaking on said streamController. I drop an NSLog in there and I never see it firing. I'm completely puzzled as to why, because I'm releasing the controller in my dealloc method for my view controller.
from view controller interface...
StreamController *streamController;
#property (nonatomic, retain) StreamController *streamController;
from view controller implementation...
#synthesize streamController;
- (id)init {
[super init];
self.streamController = [[StreamController alloc] init];
}
- (void)dealloc {
NSLog(#"dealloc view controller");
[streamController release];
[super dealloc];
}
from StreamController implementation...
- (void)dealloc {
NSLog(#"dealloc stream controller");
[super dealloc];
}
this last dealloc NEVER gets called. Why?
I believe you are just leaking memory,
if your property has retain attribute then you should take a look at the following examples:
//A
self.streamController = [[StreamController alloc] init];
//B
StreamController * st = [[StreamController alloc] init];
self.streamController = st;
[st release];
//C
streamController = [[StreamController alloc] init];
if you check retain counts you will see that in A approach your streamController object will have a retainCount of 2, while in B it will be only 1.
Reason:
In A by doing [[StreamController alloc] init]; your object has already a retainCount of 1 before passing it to your property. Then, since you declared it as retain, it will be retained, hence it's retainCount becomes 2.
In B is basically the same but you are releasing the object just after you pass it to your property. Hence, it ends with it's retainCount in 1. (This is what we want)
In C you are not using the property, you are setting the value directly. Hence it will be retained only once. This is fine in this case because is the initialization.
I will suggest to use B or maybe C if you are sure that streamController is nil (like the initialization of your object)
Hope this helps