iOS app crashes at alert view dismissal - ios

I've a problem with some UIAlertView I instance in a view controller's method. This UIViewController is presented from another UIViewController, and at a certain point I display an UIAlertView from an instance method this way:
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Upload Error", #"")
message:NSLocalizedString(#"It was not possible to complete the upload, do you want to try again?", #"")
delegate:self
cancelButtonTitle:NSLocalizedString(#"Cancel", #"")
otherButtonTitles:NSLocalizedString(#"Accept", #""), nil];
[alertView show];
I can dismiss the presented UIViewController before or at the time this alert view is shown, what causes that such alert view is shown when the presented view controller is not on screen anymore, so the alert view is shown in top of the presenting view controller. Then, when tapping one of the alert view's buttons, app crashes, I guess because its delegate was the presented view controller and it does not exist. How could I avoid this situation?
Thanks!

Either dismiss the alert view by calling dismissWithClickedButtonIndex:animated: before your presented view controller is about to be dismissed, possibly in its viewWillDisappear: or an appropriate method. Or if you want the alert view to remain on screen even after presented view controller is gone, pass the presenting view controller reference to the presented view controller and set the alertView's delegate to the presenting view controller.

The answer depends on the behavior you want to achieve.
First check UIAlertView documentation:
delegate: The receiver’s delegate or nil if it doesn’t have a delegate.
If you don't want to do 'something special' depending on the user
action, pass null.
If you want to do 'something special' depending on
the user action create a special delegate to handle the user action and keep that one alive.

Related

Difference between `present` & `push` ViewController

dismissViewController method not working to get previous viewcontoller
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
popViewController work and go to previous viewcontroller
[self.navigationController popViewControllerAnimated:YES];
i want to pass data like below please help me.but as i describe dismissViewController method not working.
[self.navigationController dismissViewControllerAnimated:YES completion:^{
HomeVC *loading;
loading.IdNameLabel.text=display;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Code" message:display delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}];
thank in advance.
Update
-(void)viewWillAppear:(BOOL)animated{
self.IdNameLabel.text=self.GetscanResult;
}
this method contain in HomeVC.when dismiss navcontroller it shows HomeVC.
is upper method can call after dismiss viewcontroller?
SOLUTION
this is very stupid question when i am at beginner level.
here is specification about it.
it will depend on method which will you Present || Push viewController.
Delegate methods will work with protocol delegate method when view controller present.
The method you need to use to go back depends on how you showed the view controller.
The first of the two common ways are by using a navigation view controller to push and pop view controllers off the stack.
The other common way is to present and dismiss a view controller modally.
You cannot for example present a view controller modally, and expect to be able to pop it off from the navigation controller, or vice versa.

ios 7 showing alert view in viewDidAppear causes view to not appear

I'm pushing a view on to my navigation controller -
[self.navigationController pushViewController:_gameOverViewController animated:YES];
In the new view's viewDidAppear, I show an alert view -
UIAlertView* alert = [[[UIAlertView alloc]
initWithTitle:#"alert title"
message:#"some text"
delegate:self
cancelButtonTitle:#"Rate It!"
otherButtonTitles:#"No Thanks",
#"Don't ask again", nil] autorelease];
[alert show];
In iOS 6 and earlier this works fine. The 'gameOver' view is visible behind the alert view. Once the alert view is dismissed the game over view is visible. In iOS 7, the alert view shows over the previous view. When the alert view is dismissed, the previous view is still visible. The 'gameOver' view is never presented to the user.
Is there a better way to show UIAlertView in iOS 7?
It came down to popping a view off the navigationcontroller and pushing a new one on at the same time. in ios6 and below this worked fine. in ios7 it appears that you cant push a new view onto the stack until the previous animation has stopped.

Some code not executing in a method called from another ViewController

My problem
I have a standard UIViewController. With the press of a button, it loads a form sheet modal view controller. When dismissing this modal view with the press of a UIBarButtonItem I call a method by doing:
ViewController *main = [[ViewController alloc] initWithNibName:nil bundle:nil];
[main updateLabel];
In the method -(void)updateLabel in the main ViewController I'm setting the text of a label, but the label won't change. But I know the function gets called, because if I do a NSLog(#"Method call test); instead of label.text = #"Test" I can see the message in console.
What am I doing wrong? It must be the way I'm calling the method in the main ViewController, because I can easily change the label anywhere else.
What I want to do:
When dismissing a modal view controller, I want a method to be called in the main view controller, and in this case change the text of a label.
Thanks for your help!
You're creating a new instance of ViewController with that code, not getting a pointer to the one you already have.
If ViewController is the controller that presented the modal view, then you can get a pointer to it with,
ViewController *main = self.presentingViewController;
A better way to do this would be to use the delegate pattern.
https://developer.apple.com/library/ios/documentation/general/conceptual/DevPedia-CocoaCore/Delegation.html
The following is a design pattern suggestion
The modal view controller shouldn't know how to dismiss itself, that is the responsibility of the presenting view controller. After all, it could have been presented in many different ways (modally, popover, push navigation). Using the delegate pattern, the modal view controller would tell its delegate that it should be dismissed when the bar button item gets pressed. The delegate, which is the presenting view controller, would then dismiss the modal view and update the label mentioned in your question.

UIAlertView hidden behind View

I presented a view controller with the presentModalViewController:animated: method. Let's call this view myView. On myView, I have a button and when tapped, it is supposed to create a UIAlertView and show it.
However, when I tap this button, the alertView is created but doesn't appear on top of myView. Instead, it is hidden behind myView.
Note: To verify that the alertView is hidden behind myView, I added a second button on myView and when it is tapped, the myView view controller dismisses itself (i.e. [self dismissModalViewControllerAnimated:YES]). When myView is dismissed, the alertView appears.
Any idea why the alertView is hidden behind myView?
I think after you show UIAlertView you are adding a subview on UIWindow. And it's above UIAlertView in UIWindow layer.
Make sure you don't add anything on UIWindow as it is not a good practice.
If you still wan t to carry out adding subview just send that subviewToBack:
Best of luck
I have the same problem. In Controller1, I present Controller2, and in Controller2 I create an alertView. But the alertView is put behind the Controller2's view.
I found that if I create the alertView not from any viewController(by using a public function), the alertView will appear at the front of the screen.
+ (void)alertShow:(NSString *)alertMsg {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertMsg
message:nil delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
[alert show];
[self performSelector:#selector(dismissAlertView:) withObject:alert afterDelay:2.5];
}
Hope it will solve your problem.
I was having this problem, also. It was intermittent, but I believe it related to displaying the alert on a background thread.
As of Xcode 9, Swift 4:
To test if function is running on main thread, use: Thread.current.isMainThread
print("On main thread: \(Thread.current.isMainThread)")
To display alert, or perform any operation on main thread, use OperationQueue.main:
OperationQueue.main.addOperation {
// code to perform on main thread
}

Push to new view controller only if textfields are correct

Currently using Xcode 4.2 and I have two view controllers (1 and 2). I have a number of textfields in viewcontroller1 that need to be filled in before the user is able to click the "Next" button which then goes to viewcontroller2. I have got alertdialogs that popup if the user hasn't filled in all the textfields.
I have used the storyboard to segue the button click which works fine, except if the textfields are empty, my alertdialog pops up but the view controller still changes to number 2.
How do i make it so that only if my if/else statements are met, does the next button go to the next view controller.
I am using a navigation controller to control the view controllers.
I tried to put the following code into the if/else statement but it didn't work:
UIViewController *secondViewController = [[SecondViewControllerClass alloc] initWithNibName:#"<name of xib>" bundle:nil];
[self presentModalViewController:secondViewController animated:YES];
Now there was a few things I was unsure about when trying to find out how to use this method. Do i need to import the SecondViewController.m at the top of the firstviewcontroller.m?
NSString has a helpful property called length, which will return nil if a textfield contains no text. If you need to check, call:
if (!myTextField.text.length) {
//no text in the box
}
Simple enough, since you have already set up the alert boxes to pop up if something is wrong with the textbox input, make sure the alert box show/init code is before the code that changes the view and do this:
if(//something is wrong with the textbox input)
{
UIAlertView* alert = [[UIAlertView alloc] initWith...
[alert show];
//Add a return! If the method is not IBAction or void, just return nil
return;
}
Voila!

Resources