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
}
Related
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.
I have an UIAlertView that is dismissed by a timer after a few seconds. Some users want to dismiss the alert view earlier simply by tapping the alert view itself.
I thus tried to add a single tap gesture recognizer to the alertView, but its action was not called. I then read on SO that the alert view must be in a view hierarchy before the gesture recognizer can be added. I am not sure about this but anyway I thus moved adding of the gesture recognizer to the alert view delegate method didPresentAlertView:, but the action is still not called.
Here is my code. Any help is appreciated.
The initialization of the alert view:
alertView = [[UIAlertView alloc] initWithTitle:#"title" message:#"message" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
}
[alertView performSelectorOnMainThread:#selector(show) withObject:self waitUntilDone:NO];
[self performSelector:#selector(dismissAlertAfterDelay:) withObject:alertView afterDelay:4.0];
The delegate method where the gesture recognizer is added:
- (void)didPresentAlertView:(UIAlertView *)alertView{
alertView.userInteractionEnabled = YES;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget: self action:#selector(dismissAlert:)];
singleTap.numberOfTapsRequired = 1;
[alertView addGestureRecognizer:singleTap];
}
and the action method that is NOT called:
-(void)dismissAlert:(UITapGestureRecognizer *)sender{
UIAlertView *alertView = (UIAlertView *)sender.view;
[alertView removeFromSuperview];
}
I know that an alert view is displayed in a separate window, but I believe anyway that a gesture recognizer added to it should call the action method when user interaction is enabled for the alert view.
Any suggestions?
UIAlertView is, despite its name ending in View, a model class in iOS 7. It never gets added to the view hierarchy. That's why adding subviews to it doesn't work either: they are added, but their parent isn't in the view hierarchy. The view hierarchy that's presented when you show an alert is private and is not to be messed with.
I suggest following the HIG by just using a dismiss button. If you really, really want the entire alert to be able to be tapped, look at SDCAlertView. It's a UIAlertView clone I wrote that does act like an actual view.
I need to show an UIAlertView before a user leaves a certain view, either by tapping a 'back' navigation bar button or by tapping one of the tab items in the tab bar I have, in order to ask him for confirmation. It would be a two-button alert, a 'Cancel' one to stay in the view, and an 'Accept' one to leave. I need to do this because I have to make the user aware that unsaved changes will be lost if leaving.
I tried to do this by creating and showing the alert view in the viewWillDisappear: method:
- (void)viewWillDisappear:(BOOL)animated
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Exit", #"")
message:NSLocalizedString(#"Are you sure you want to leave? Changes will be discarded", #"")
delegate:self
cancelButtonTitle:NSLocalizedString(#"Cancel", #"")
otherButtonTitles:NSLocalizedString(#"Accept", #""), nil];
[alertView show];
[super viewWillDisappear:animated];
}
But the view is pop anyway, and the alert view is shown after that and app crashes since its delegate is the view controller that has been already pop from the navigation stack... I don't find the way to solve this scenario, can anybody help me?
Thanks!
Showing the alert view when viewWillDissapear won't work, because the view is already dissapearing, it's on its way to be removed.
What you can do, is add yourself a custom action when the back button is pressed, then you decide what to do when the back button is pressed, you can show the alert view, and then in one of the buttons procedd to dismiss the view, something like this:
- (id)init {
if (self = [super init]) {
self.navigationItem.backBarButtonItem.target = self;
self.navigationItem.backBarButtonItem.action = #selector(backButtonPressed:);
}
return self;
}
Then show the alert view when the back button is pressed:
-(void)backButtonPressed:(id)sender
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Exit", #"") message:NSLocalizedString(#"Are you sure you want to leave? Changes will be discarded", #"") delegate:self cancelButtonTitle:NSLocalizedString(#"Cancel", #"") otherButtonTitles:NSLocalizedString(#"Accept", #""), nil];
[alertView show];
}
Now, when the confirmation button in the alert view is pressed, just call:
[self.navigationController popViewControllerAnimated:YES];
Or do nothing if the user cancels
I would be tempted to move the data manipulation you're trying to protect into a modal view controller and handle the validation on whatever action you choose to have dismiss the modal presentation. To me, that's the point of modal: something that has to be completed before interacting with the rest of the app.
As you can see I'm trying to performSegue from Photo Action View Controller to Setting View Controller (UITableViewController).
So I'm performing from PhotoActionViewController directly (not using buttons etc.) because I want to perform this segue when user taps on one option from showing AlertView. Everything works like charm untill I set Class for the SettingsViewController. The segue performs but I can't see any UITableViewCell. How can I get this wor form me?
Here is my code:
- (IBAction)imageViewTapped:(UITapGestureRecognizer *)sender
{
BlockAlertView *alert = [BlockAlertView alertWithTitle:#"New Photo" message:#"Decide what you would like to do with this photo"];
[alert addButtonWithTitle:#"Create New Project" block:^{
// Pushing to New Project Settings Controller
[self performSegueWithIdentifier:#"NPSSegue" sender:self];
}];
[alert addButtonWithTitle:#"Add To Existing Project" block:^{
NSLog(#"Add to existing");
}];
[alert setCancelButtonWithTitle:#"Cancel" block:nil];
[alert show];
}
I'm not posting prepareForSegue as it is empty for this moment and I don't know if anything should be there.
whenever using segue programmatically we need to connect segue through one scene to another scene(viewcontroller) so create a button make it invisible and connect it to the destination scene and in uialertview delegate make button setEnabled:true and before pls set the segue Idetifier thanks and sorry for poor english.......
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.