I have Simple popOver controller in my project. i can dismiss it using action button with following code.
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
but sometimes app gets crash if i do something on that viewController
before dismiss it.
Example : There is a pickerView for selection and post button. but without posting it if i did some selection and cancel it im getting this error. its only happening occasionally. not everytime. if it happens onetime then it might happen everytime after that.
Can someone explain? is it memory leak or something?
I think have solved the problem . in that PopOver new window i was using locationManager and i was using just
[locationManager stopUpdatingLocation];
but i have added following thing as well
locationManager = nil;
no crash anymore
Sometimes if you have dealloc function as mentioned below, this issue may occur.
- (void)dealloc {
[_yourview release]; //don't do this
[super dealloc];
}
I hope this might help some one else
Related
In iOS, I pop from current viewController into previous one, but it doesn't go into dealloc.
Is this because there is another pointer pointing towards the current viewController, either in a different viewController or in the current one?
This is where I pop to previous view:
- (IBAction)fileUploadCancelTouched:(UIButton *)sender {
[self.fileToUpload cancel];
[self.view hideToastActivity];
[self.greenprogressBar removeFromSuperview];
[self.subView removeFromSuperview];
self.fileUploadCancelButton.hidden = YES;
if (self.commandComeBackToFinalScreen == 1) {
[self.navigationController popViewControllerAnimated:YES];
}
}
This is my dealloc function:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
self.greenprogressBar = nil;
self.fileUploadCancelButton = nil;
self.fileToUpload = nil;
[buttonHome_ release];
[buttonTestMeAgain_ release];
[buttonMarkMyTest_ release];
[examId_ release];
[sender_ release];
self.ob = nil;
[_fileUploadCancelButton release];
[super dealloc];
}
Check to make sure that ARC is not enabled in your project. If it is not ARC enabled then dealloc should be called unless your code is retaining your view controller. You should check through the Instruments tool if your pop commands reduces memory or not.
There may be some other reasons as mentioned in another answer that I am posting below:
The obvious reason is that something is retaining your viewController. You will have to look closely at your code. Do you do anything that in your class that uses delegates, since they sometimes retain the delegate. NSURLConnection will retain your class, and so does NSTimer. You can scatter code in you class and log your class's retain count, and try to find out where. In the code you showed so far the retain could should just be 1, since the class is only retained by the navigation controller.
Also, before you pop your view, get a reference to it, pop it with NO animation, and then send it some message that has it report the retain count (this would be some new method you write). That new method could also log other things, like whether it has any timers going, NSURLConnections, etc.
First of all, get rid of [super dealloc]. I know that's intuitive, but the documentation says don't do it.
In my own case, I had an observer & timer in my dealloc method, but that wouldn't run since the timer had a strong pointer to the controller.
Created a dedicated clean up method which removed the observer & invalidated the timer. Once that ran, the controller was correctly deallocated.
I have a UIActivity subclass that creates its own activityViewController:
- (UIViewController *)activityViewController {
WSLInProgressViewController* progressView = [[[WSLInProgressViewController alloc] init] autorelease];
progressView.message = [NSString stringWithFormat:NSLocalizedString(#"Posting to %#...",#"Posting to..."),
self.activityType];
return progressView;
}
I've add a full repro on GitHub.
According to the documentation, you aren't supposed to dismiss this manually. Instead, the OS does that when you call activityDidFinish:. This works fine when ran on an iPhone.
When I say "works," this is the sequence of events that I'm expecting (and see on the iPhone):
Display the UIActivityViewController
User presses my custom activity
My view controller appears
I call activityDidFinish:
My custom view controller is dismissed
The UIActivityViewController is also dismissed
However, when I run this same code on the iPad Simulator -- the only difference being that I put the UIActivityViewController in a popup, as the documentation says you should -- the activityViewController never dismisses.
As I say, this is code wo/the popUP works on the iPhone and I have stepped through the code so I know that activityDidFinish: is getting called.
I found this Radar talking about the same problem in iOS6 beta 3, but it seems such fundamental functionality that I suspect a bug in my code rather than OS (also note that it works correctly with the Twitter and Facebook functionality!).
Am I missing something? Do I need to do something special in the activityViewController when it's run in a UIPopoverViewController? Is the "flow" supposed to be different on the iPad?
The automatic dismissal only appears to happen when your 'activity' controller is directly presented, not wrapped in anything. So just before showing the popup it's wrapped in, add a completion handler
activity.completionHandler = ^(NSString *activityType, BOOL completed){
[self.popup dismissPopoverAnimated:YES];
};
and you'll be good.
I see the question is quite old, but we've been debugging the same view-controller-not-dismissing issue here and I hope my answer will provide some additional details and a better solution than calling up -dismissPopoverAnimated: manually.
The documentation on the UIActivity is quite sparse and while it hints on the way an implementation should be structured, the question shows it's not so obvious as it could be.
The first thing you should notice is the documentation states you should not be dismissing the view controller manually in anyway. This actually holds true.
What the documentation doesn't say, and what comes as an observable thing when you come across debugging the non-dissmissing-view-controller issue, is iOS will call your -activityViewController method when it needs a reference to the subject view controller. As it turns out, probably only on iPad, iOS doesn't actually store the returned view controller instance anywhere in it's structures and then, when it wants to dismiss the view controller, it merely asks your -activityViewController for the object and then dismisses it. The view controller instantiated in the first call to the method (when it was shown) is thus never dismissed. Ouch. This is the cause of the issue.
How do we properly fix this?
Skimming the UIActivity docs further one may stumble accross the -prepareWithActivityItems: method. The particular hint lies along the following text:
If the implementation of your service requires displaying additional UI to the user, you can use this method to prepare your view controller object and make it available from the activityViewController method.
So, the idea is to instantiate your view controller in the -prepareWithActivityItems: method and tackle it into an instance variable. Then merely return the same instance from your -activityViewController method.
Given this, the view controller will be properly hidden after you call the -activityDidFinish: method w/o any further manual intervention.
Bingo.
NB! Digging this a bit further, the -prepareWithActivityItems: should not instantiate a new view controller each time it's called. If you have previously created one, you should merely re-use it. In our case it happily crashed if we didn't.
I hope this helps someone. :)
I had the same problem. It solved for me saving activityViewController as member and return stored controller. Activity return new object and dismiss invoked on new one.
- (UIViewController *)activityViewController {
if (!self.detaisController) {
// create detailsController
}
return self.detailsController;
}
I pass through the UIActivity to another view then call the following...
[myActivity activityDidFinish:YES];
This works on my device as well as in the simulator. Make sure you're not overriding the activityDidFinish method in your UIActivity .m file as I was doing previously. You can see the code i'm using here.
a workaround is to ask the calling ViewController to perform segue to your destination ViewController via - (void)performActivity although Apple does not recommend to do so.
For example:
- (void)performActivity
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
[self.delegate performSomething]; // (delegate is the calling VC)
[self activityDidFinish: YES];
}
}
- (UIViewController *)activityViewController
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
UIViewController* vc=XXX;
return vc;
}
else
{
return nil;
}
}
Do you use storyboards? Maybe in your iPad storyboard, the UIActivityIndicatorView doesn't have a check on "Hides When Stopped"?
Hope it helps!
So I had the same problem, I had a custom UIActivity with a custom activityViewController and when it was presented modally it would not dismiss not matter what I tried. The work around I choose to go with so that the experience remained the same to the user was to still use a custom UIActivity but give that activity a delegate. So in my UIActiviy subclass I have the following:
- (void)performActivity
{
if ([self.delegate respondsToSelector:#selector(showViewController)]) {
[self.delegate showViewController];
}
[self activityDidFinish:YES];
}
- (UIViewController *)activityViewController
{
return nil;
}
Then I make the view controller that shows the UIActivityViewController the delegate and it shows the view controller that you would otherwise show in activityViewController in the delegate method.
what about releasing at the end? Using non-arc project!
[progressView release];
Many Users have the same problem as u do! Another solution is:
UIActivityIndicatorView *progress= [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125, 50, 30, 30)];
progress.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
[alert addSubview:progress];
[progress startAnimating];
If you are using storyboard be sure that when u click on the activityind. "Hides When Stopped" is clicked!
Hope that helped...
I have a page with a back button that takes me to an inbox. I do this in viewWillDisappear -
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[inboxToolbar removeFromSuperview ];
[inboxToolbar release];
}
If I do this a few times, the app crashes and the exception thrown is "unrecognized selector sent to instance". This happens very intermittently. Any thoughts on how to go about fixing / debugging it?
Assuming the crash is accessing your inboxToolbar ivar, change your code to the following:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[inboxToolbar removeFromSuperview ];
[inboxToolbar release];
inboxToolbar = nil;
}
This will ensure inboxToolbar does not keep a pointer to a deallocated object. You could also have other issues, would need to see the crash log and more of your code to be sure.
add an exception break point to see where it is being thrown, you probably are sending a message to an object that isn't of the class that you believe it to be, after you have stopped on the exception breakpoint, you can hover over the variable to see what classes they belong to.
if that doesn't help post the actual message and perhaps we can help more, could be iOS version issue, etc.
Try checking whether it will respond to your method first...
if ([inboxToolbar respondsToSelector:#selector(removeFromSuperview)]) {
[inboxToolbar removeFromSuperview];
}
I'm displaying a modal view called "rule" from a round rect button. In that "rule" modal view i'm displaying another modal view called "newRule" when user clicks the Create Rule button.
When i'm quitting from the "newRule" modal view the app crashes. Here's the code i had written for quitting the "newRule" modal view.
[self dismissModalViewControllerAnimated:YES];
Nothing is displayed in the console. When i tried to debug the code, it displayed a EXC_BAD_ACCESS after the dealloc method. My dealloc method looks like this:
[label release];
label = nil;
[imageArray release];
imageArray = nil;
[languageElementsArray release];
languageElementsArray = nil;
[super dealloc];
Please help me.
Is the label a UILabel object? Also what are in the arrays? Views are automatically released once their superview is released, so releasing a subview after its superview has been released (or releasing the subview then the superview) will cause an crash similar to the one you describe
I'm experiencing something similar. When I comment out the last line ( [super dealloc] ), it then works. Does this make a difference for you?
If you happen to be using Automatic Reference Counting in Xcode 4.2, then you should not have a [super dealloc] at all—which would result in this error.
Of course, in that context you likely should not be releasing these other objects either.
I'm making a split-view based iPad application(Portrait mode only), and I want to know how to recover initial state after viewDidUnload is called.
When split-view application started for the first time,
-splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
is called automatically (right after -viewDidLoad).
I prepares UIBarButtonItems in the method.
If I open modal dialog or something with UIWebViewController (it consumes a lot of memory), application receives memory warning, viewDidUnload(s) are called.
When I close the modal dialog, -viewDidLoad is called automatically, but this time
-splitViewController:willHideViewController:withBarButtonItem:forPopoverController: is not called.
I prepares UIBarButtonItems in
-splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
but it is not called, so buttons are dismissed.
In that case, should I call the method manually?
I found similar posting here.
https://github.com/grgcombs/IntelligentSplitViewController/issues/6
Thanks.
I don't know it is OK to answer to my own question, but maybe I found an answer for this. http://osdir.com/ml/cocoa-dev/2011-02/msg00430.html
It says that we should preserve BarButtonItems in viewDidUnload, and load it in viewDidLoad.
It seems working fine.
- (void)viewDidUnload {
[super viewDidUnload];
self.toolbarItems = self.toolbar.items; // property with retain policy
}
- (void)viewDidLoad {
[super viewDidLoad];
if (self.toolbarItems) {
self.toolbar.items = self.toolbarItems;
self.toolbarItems = nil;
}
}