I have a modal view controller which is crashing when it dismisses itself. The error is EXC_BAD_ACCESS (yipee). I am tryin got use NSZombie to work out the problem. I get am getting the following :
2010-10-20 17:15:58.936 [24058:207] AddRunningClient starting device on non-zero client count
2010-10-20 17:16:06.846 [24058:207] * -[ViewController retain]: message sent to deallocated instance 0x6c2d4a0
What does this mean - does it mean that a message was sent to the Viewcontroller or that a message was sent to an object in the Viewcontroller ?
I am really stuck as the thread seems to be main :(
Thanks all in advance for any help,
Martin
EDIT
Thanks all for the quick replies. Here is how I am presenting the view controller :
-(IBAction)letsstartGame {
ViewController * sl = [[ViewController alloc] initWithNibName:#"ViewController" bundle:[NSBundle mainBundle]];
self.viewLink = sl;
[sl release];
[mainMenu stop];
[mainMenu setCurrentTime:0.0];
[self presentModalViewController:viewLink animated:NO];
[viewLink release];
self.viewLink = nil;
}
And dismiss like this :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (waitingOver) {
[backgroundMain stop];
[fireworks stop];
[self dismissModalViewControllerAnimated:NO];
}
}
That means that you had an instance of an object of type ViewController, it was deallocated, and then you tried to retain it.
edit
You're over-releasing the object. Here's what you're doing:
ViewController * sl = [[ViewController alloc] initWithNibName:#"ViewController" bundle:[NSBundle mainBundle]]; //allocated, has a +1 retain count
self.viewLink = sl; //assuming a retain property, has a +2 retain count
[sl release]; //releasing, now has +1 retain count
....
[viewLink release]; //releasing, now has a 0 retain count
self.viewLink = nil; //attempting to release stale pointer, will result in a crash (perhaps not immediately, but eventually)
Get rid of the [viewLink release] line. It is wrong to have that in there.
It means you are sending a message to a deallocated instance.
So somewhere in your code you have failed to retain an object (probably ViewController) or have released it prematurely.
If you can post your code where you create the View Controller that might be helpful for us to debug.
The message is basically saying that you are trying to send a message (call a function) on/to an object that has already been dealloc'd (released and the memory freed). If you could send more code, I could perhaps attempt to determine why.
Related
Here is my code:
-(void)btnAction
{
mapController = [[MKMapController alloc] initWithNibName:#"MKMapController" bundle:nil];
mapController.delegate = self;
mapController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:mapController animated:YES];
[mapController release];
}
I am getting the crash message as:
-[MKMapController respondsToSelector:]: message sent to deallocated instance 0x79ccc90
Guy's please help me how to resolve this..!!
Thanks to all,
Monish.
Release your mapController in dealloc method.
-(void) addBookmarkTapped:(id)sender {
BookmarkAddViewController *bookmarkAddViewController =
[[BookmarkAddViewController alloc] initWithName:currTitle link:self.addressBar.text];
[self presentModalViewController:bookmarkAddViewController animated:YES];
[bookmarkAddViewController release];
}
code above cause 'EXC_BAD_ACCESS' when back to the main controller. Same error if I make bookmarkAddViewController 'autorelease'.
It will not crash if I remove the release, but it will cause memory leak?
[bookmarkAddViewController release];
I see many examples doing the same way, why it doesn't work in my case?
It might have to do with your init method in bookmarkAddViewController.(Please post.) Make sure you dismiss the controller properly with [self dismissModalViewControllerAnimated:YES];.
I don't know what's going wrong here. The crash happens when switching back and forth between views.
Here's what instruments gives me:
Clicking into it references this code with the first action :
-(IBAction)pushnews; {
NewsViewController *news = [[[NewsViewController alloc]init]autorelease];
news.title =#"Page";
[self.navigationController pushViewController:news animated:YES]; }
I use autorelease sometimes but usually I just release it my self. Should I get rid of autorelease and add [news retain]
What am I doing wrong?
Edit based on answers:
Following EmptyStack's Advice: ViewWillDisappear Code looks like this:
- (void)viewWillDisappear:(BOOL)animated {
webView.delegate = nil; }
This seems to resolve issues (pending more testing)
In viewdidload I said: webView.delegate = self;, which may have been the issue!
My guess is that, there is a UIWebView in NewsViewController, and it is causing the crash. It is possible that, a delegate method of web view is called after the web view is released. If so, try to setwebView.delegate = nil; in NewsViewController's viewWillDisappear: method.
try this instead :
-(IBAction)viewcontroller;
{
NewsViewController *news = [[NewsViewController alloc]init];
news.title =#"Page";
[self.navigationController pushViewController:news animated:YES];
[news release];
}
I got troubles implementing InAppPurchase. My implementation of purchase is in modal view controller (AppUpgradeViewController), that I present from another modal view. I do it like this:
AppUpgradeViewController * appUpgradeViewController = [[AppUpgradeViewController alloc] init];
appUpgradeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
appUpgradeViewController.delegate = self;
[self presentModalViewController:appUpgradeViewController animated:YES];
[appUpgradeViewController release];
Then, in my upgrade view I do the following:
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
NSSet *productIdentifiers = [NSSet setWithObject:kInAppPurchaseProUpgradeProductId];
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
self.productsRequest.delegate = self;
[productsRequest start];
Then I have implemented
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
where I do:
[self.productsRequest release];
and then I have other required methods.
The problem is when I show modal, and quickly dismiss it then after few seconds i got the following on console (I turned on NSZombieEnabled):
*** -[AppUpgradeViewController respondsToSelector:]: message sent to deallocated instance 0x2e91f0
I suppose that it's something with that product request, but I don't know how to debug or fix it. It seems that the answer for request comes to this controller just after it's dismissed (and deallocated), but I don't know how to prevent it from receiving messages after dismiss/dealloc.
Thanks for any help!
I had the same problem. Not with a modal view, but with a pushed view on the navigation controller stack. When I quickly navigated back before my product information was loaded via SKProductsRequest, it also throws me an message sent to deallocated instance exception. I solved this by calling the cancel method (see reference) on my SKProductsRequest object.
Additional to this I also set the delegate to nil.
This is my product request:
NSSet *productIdentifiers = [NSSet setWithObject:#"MY_IDENTIFIER"];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
and this is what I called in the dealloc method to cancel it.
productsRequest.delegate = nil;
[productsRequest cancel];
productsRequest = nil;
I also removed the observer from the SKPaymentQueue like described in this answer for another question.
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
You probably forgot to nil your request delegate in AppUpgradeViewController's dealloc:
- (void)dealloc {
...
productsRequest.delegate = nil;
[productsRequest release], productsRequest = nil;
...
[super dealloc];
}
I guess that's because you have released your productsRequest, but it seems you haven't set the pointer to nil which means it's still pointing at the now-invalid memory location.
How is the productsRequest property defined ? If it has the retain option, then instead of:
[self.productsRequest release];
you need to do:
self.productsRequest = nil; // Property will do the release for you.
If it has the assign option, then you need to do:
[self.productsRequest release];
self.productsRequest = nil; // Or else some might access this pointer,
// which now might point to nirvana.
Is it because you're doing this:
[appUpgradeViewController release];
too early?
Try doing it in the dealloc method of whatever class you're allocing it in.
Providing you're not allocing it more than once, of course. This would also require you to move your declaration into the class header.
Swift 3
It's a good idea to close the request if you started it. This is a safe way to do it in Swift.
// strong reference at top of class
var productRequest: SKProductsRequest!
// at some point you will fetch products
// on deallocating the window
if productRequest != nil {
productRequest.cancel()
productRequest.delegate = nil
}
I'm dealing with viewDidUnload and dealloc methods and I've founded a problem when calling [super dealloc]; in parent view controller.
I have a lot of view controllers with custom code which I have putted outside on a parent view controller. So, when defining my view controllers I set a reference to the super class:
#interface LoginViewController : AbstractViewController
Then, at the dealloc method I call the AbstractViewController dealloc method:
//(Login View Controller code)
- (void)dealloc {
[user release];
[passwd release];
[super dealloc];
}
[super dealloc] execute the following code:
//(Abstract View Controller code)
- (void)dealloc {
[dbUtils release];
[loadingView release];
[super dealloc];
}
If I simulate a memory warning on iPhone Simulator, the following exception is thrown:
2010-03-03 11:27:45.805 MyApp[71563:40b] Received simulated memory warning.
2010-03-03 11:27:45.808 MyApp[71563:40b] *** -[LoginViewController isViewLoaded]: message sent to deallocated instance 0x13b51b0
kill
quit
However, if I comment the [super dealloc] line in AbstractViewController the exception is not thrown and my app still running.
Thank you for your help once again!
It looks like you're freeing your view controller but then trying to use it again. When you free your view controller because of the memory warning, remember to set the pointer to nil so you don't accidentally use it again. i.e. something like
[myLoginViewController release]; //!< Triggers the dealloc call
myLoginController = nil; //!< Makes sure we never use it again
or, if myLoginViewController is a property you can do this in a neater way :
self.myLoginViewController = nil;
Hope that helps,
Sam
Notice -didReceiveMemoryWarning does not trigger -dealloc, it triggers -viewDidUnload. So I guess it is your implementation of -viewDidUnload that does something wrong that causes the controller's final retention to be released so -dealloc is called. I've just encountered this problem in my code which is caused by a retain recycle that is released in -viewDidUnload.
This happened to me and took a while to figure out. One of the delegates was trying to send a message because the delegate was self and it was a strong reference. when I made it weak it seems to have fixed it.