Crash when UIAlertView dismissed - ios

I am using ARC.
I show an alert view after a user taps a UITableView cell.
99% of the times everything works great.
NOW TO THE WEIRED PART
I have this view hierarchy -
UITableView --> First UIViewController --> Child UIViewControllerControllers
The crash only appears after I open one, specific child UIViewControllers. After I enter all the other child viewControllers the alert view works great. If I enter the "problematic" view controller even once, The UIAlert view will crash even 5 minutes later and even if I get into all the other view controllers.
I have to say again that the alertView is presented in the root UITableView. And that it crashes even if the alert view callback method is only NSLoging.
The crash report is:
*** -[ReviewViewController isKindOfClass:]: message sent to deallocated instance 0x20bea8d0
while 'ReviewViewController' is the problematic viewController.
Thanks
Shani

You're setting the delegate of the UIAlertview to the calling UIViewController. That UIViewController is being de-allocated in certain cases when you navigate away from it.
If you require a delegate to respond to the UIAlertView, you'll have to structure your code so that the delegate doesn't get de-allocated before the UIAlertView will be dismissed.

Related

How do I display an alert over a PageViewController after a popover dismissal?

I have a a VC structure like this
UIPageViewController -> detailViewController -> popoverviewcontroller
The popoverviewcontroller is dismissed using an unwind segue, bringing us back to the detailviewcontroller
Now, after the popover is done being dismissed, I would like to refresh the pages on the pagecontroller, since the action the user takes has changed the data.
I would also like to display an alert notifying the user about whether they were successful.
So I tried putting this code in the pageViewcontroller
- (IBAction) unwindFromPopup:(UIStoryboardSegue*)unwindSegue{
[self refreshPages];
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:#"alert" message:#"this should appear" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alertController animated:YES completion:nil];
}
I tried moving the above code to the detail view controller instead, but I am getting no result from this. No error or anything, just a complete lack of alert. I put a breakpoint in the segue, and the code gets called. But no alert.
I thought of putting the code in one of the respective viewDidAppear methods, but for some reason viewDidAppear does not get called for either the pageviewcontroller or the detailview controller after I dismiss the popup.
So at this point I have no idea how to make this alert appear.
Do I need to post my full code, or is my problem apparent with the details I've included?
Thanks - based on your comment ... long ago in a distant version of iOS I performed all the possible segues and noted what gets called when and have a table of that that I based my answer on. I must admit, nowadays I get most done using the presentation controller delegate.
Anyhow, to reply to your question, when you pop or modally present a controller, the controller that is being presented will message beingPresented and beingDismissed when it is done and you might be able to use this for what you are trying to do.
When you push a controller it will message isMovingToParentViewController when shown and isMovingFromParentViewController when dismissed, again in the controller being presented.
Back to a pop ... it will message prepareForSegue in the presenting VC and viewWillAppear and viewDidAppear in the presented VC and, when dismissing, will message only viewWillDisappear and viewDidDisappear in the presented VC, thus your problem. At least it will also message beingDismissed as mentioned and if you can use that I am really glad for you.

dismissViewControllerAnimated sends message to zombie object

I have two UIViewControllers, VC1 and VC2. VC1 has a button that invokes a triggered Modal segue to VC2. This segue is defined in the storyboard. In VC2, the user can return to VC1 using a pan gesture that executes this line of code:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
This code has worked for a long time. However, all of a sudden when this line runs, the app crashes. I enabled zombie objects and I can see this error:
-[VC2 retain]: message sent to deallocated instance 0x7f843a81e200
I've run the zombie profiler and here are the results:
UIClassSwapper initWithCoder seems to be where the app crashes, and there appears to be a an over retained object there, but I can't get any further. When I set an exception breakpoint, I just get into the assembly code, and this isn't of any apparent help.
So, there are a couple of questions here. The first is simply what am I doing wrong in how I am presenting and dismissing this view controller? After that, I don't know how to crack into the event history to figure out how to handle this zombie object.
Any help is appreciated. Thank you!
It seems that you use ARC project. Please provide more code:
1. How you initialize presentingViewController property (and declare). Is it (nonatomic,strong)?
2. How do you put this ViewController to the screen. Is it a kind of modal view controller etc?
-- added after comment.
ARC based project decides automatically if the object is needed or not and removes it from the stack automatically. So, the only one useful recipe to avoid this problem is to add NSNotification observer and post there notifications time after time. It will keep view controller in the stack and avoid automatic release.
Another solution - check if the controller is still in the stack:
if (!self.presentingViewController) [[THECONTROLLER alloc] init];
The third one - is to use some object to declare VC1 and VC2 as class variables, and present them as modal view controller when needed. In this case, object and its variables will be kept untouched as long as any of VCs presented.
In any case, the Exception happens because ARC considers that VC is not needed anymore and releases it atomatically.

How to avoid crashes on call back to deallocated delegate objects

My application is on ARC and I still see few crashes. I then saw that I was setting my view controller as delegate of an alert view and then when the alert is on screen, on tap on "OK" button I was moving back to previous view and my current view controller was getting dealloc-ed. After it is getting dealloc-ed, I got a call from UIKit for the alert view and it crashes. As a safe handling, I created a property for UIAlertView and in the dealloc now, I am setting delegate of this UIAlertView to nil. This is working fine now.
I see another crash happening randomly:
-[CFString release]: message sent to deallocated instance 0xd2de900
My question here is that there are lot many places where I create local instances of some objects (custom view controllers or iOS objects like UIAlertView) and set my view controller as delegate of it. Do I need to create class level properties for all of them and the delegate on them to nil in the dealloc? Is there any other easy alternative to make sure no call back happens after delegate object is gone.

alertView:didDismissWithButtonIndex: message sent to deallocated instance

The problem is only happening with iOS4.3. I'm using ARC and my Base SDK is iOS6.
In -viewDidAppear of my view controller, I check if this is the first time the app has been started and if so, then I create and show a UIAlertView. I assign that UIAlertView to a strong property on the view controller and set self as the UIAlertView delegate.
self.uiAlertView = [[UIAlertView alloc] initWithTitle:#"Welcome!"
message:messageString
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:#"View Tutorial Videos", #"Email Support", nil];
When I tap one of the buttons, the app crashes complaining that -alertView:didDismissWithButtonIndex: was sent to a deallocated instance. The delegate is the view controller that is displaying the UIAlertView.
On all subsequent launches of the app, when the UIAlertView isn't shown there are no problems. The view controller is definitely not being deallocated.
If I display the UIAlertView but set the delegate to nil, then there is no problem and the app continues working, so clearly the view controller hasn't been deallocated because I can keep using it.
What is happening? This only causes a problem with iOS4.3.
EDIT: Based on suggestions in the comments, I added some more log messages in different places.
I've discovered that the view controller IS getting dealloc'd, but only if that view controller displays the UIAlertView. What in the world would cause the view controller to get dealloc'd just because it sets itself as the delegate of a UIAlertView and then displays it?
My app delegate has a strong reference to the view controller, so there is absolutely no reason that I can see for the view controller to get dealloc'd.
EDIT 2: I've discovered that during start up my main view controller is being instantiated TWICE. The first one is the one creating the UIAlertView and that one is getting dealloc'd. The second one is the one that I've been able to interact with afterwards that made me think the view controller was still there and operable.
However, I can't figure out where or why my view controller would be created twice. I don't have any alloc/init statements for the view controller. It only exists in the MainWindow_iPhone.xib.
The first time viewDidLoad is called on my view controller, the stack frame above is [UIViewController view]. The second time viewDidLoad is called on the second instance of my view controller, the stack frame above is [UINib instantiateWithOwner:options:]
EDIT 3: I've "fixed" the problem, but I don't understand why this would happen. Perhaps you can help me understand.
In my MainWindow_iPhone.xib, I created my root view controller and assigned it to an IBOutlet on my app delegate. Instead, I deleted the view controller from the xib and created it in code in the -application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions ... and the problem disappeared.
Why in the world would the view controller be created twice when in the xib?
I have this issue before. alertView:didDismissWithButtonIndex: is called after alertView: clickedButtonAtIndex:. You most likely deallocate the view controller in alertView:clickedButtonAtIndex by doing something like [self.navigationController popViewControllerAnimated:YES].
UIAlertView delegate is assign not weak reference. When delegate is deallocated, it is not set to nil automatically. That's reason why your code is crashed.
i fixed this issue commenting this method (or deleting it).
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"se apreto cancel");
}
as James Wang said, the didDismissWithButtonIndex is called after clickedButtonAtIndex so i commented it to avoid the crash.

UITextFields intermittently not allowing user interaction

I know it's a very long shot and the problem description is vague at best, but I'm hoping someone might have encountered that as well.
I have a UIViewController subclass that is being presented modally. The view of the controller contains some UIButtons and some UITextFields. The view controller might be presented multiple times during a user session; it is created every time it's presented and gets destroyed when it's dismissed. Most of the time everything works as expected, however, sometimes the text fields don't respond to user touch, i.e. tapping them does not bring up the keyboard. The buttons on the view work fine, it's just the text fields that become disabled.
What could possibly be causing this?
Turns out the reason UITextFields inside a modally presented view controller were not responding was that one of the long-living view controllers in the app called [self becomeFirstResponder] on itself, but never called [self resignFirstResponder]. It had to be the first responder in order for it to receive remote controls events when the app was playing music.

Resources