I am new to Xcode somewhat. Right now I am creating a view controller (displaying modally) which displays a form for users to input information, and click "submit" to submit the information.
I created my IBAction, and implemented a UIAlerView that informs the user the information has been sent. I would like the "Ok" button within my alert view to take them back to the original view controller. I set my Alert View delegate and implemented the following method in my .m file:
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
When I test it, nothing happens. Can anyone tell me what I am doing wrong.
You need to implement - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex delegate method ---
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
//dissmiss here
//Pre iOS 6.0
[self dismissModalViewControllerAnimated:YES];
//From iOS 5.0
[self dismissViewControllerAnimated:YES completion:nil];
}
You can also check for the button which tapped,
if(buttonIndex != [alertView cancelButtonIndex]) {
//do something
}
You need to implement the below mentioned delegate method of UIAlertView:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSString *buttonTitle = [alertView buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqual:#"Ok"]) // Check for Ok button
{
[self dismissViewControllerAnimated:YES completion:nil];
}
}
SWIFT 5
I have been away form Xcode since swift 3 and needed to do this in my new project. The below code worked for me (it presents an alert and upon closing the alert, the user is taken back to the previous view controller):
func displayAlert() {
let alert = UIAlertController(title: "Your Title",
message: "Your Message",
preferredStyle: .alert)
let defaultButton = UIAlertAction(title: "OK",
style: .default) {(_) in
// your defaultButton action goes here
self.dismiss(animated: true, completion: nil)
}
alert.addAction(defaultButton)
present(alert, animated: true) {
// completion goes here
}
}
Related
I am editing an app where I added a new UIViewController to configure a multiplayer game in one layout.
I have added two buttons for each player (top button, bot button). Each button generates an alert at the screen (remember it is in landscape orientation ) but the problem is, player 2 do not see the alert rotated, I mean, the alert is supposed to be shown in his orientation, in front of me.
As there any way to do this? I want to rotate an Alert for the player 2 will not see the information of the alert turned.
Here the alert code I have:
#IBAction func ShowAlert(){
let message = "Test"
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
alert.addAction(action)
presentViewController(alert, animated: true, completion: nil)
}
Here is a way to rotate an alert controller view, although it is not perfect. The controller tries to present based on the orientation and I found that attempting to transform it before it is presented is unsuccessful.
In order to not see "incorrect" orientation initially, you must set the alert to hidden and then make it visible once it is "presented".
let alert // setup
alert.view.hidden = true;
[self presentViewController:c animated:YES completion:^{
alert.view.transform = CGAffineTransformMakeRotation(M_PI);
alert.view.hidden = false;
}];
The only outstanding issue I have with this is that after the user interacts with the alert, it flashes back to the initial transformation (orientation dependent). I currently have not found a solution for this, but will update if I ever do.
Alternatively, using a custom "alert" would solve this problem as you would have more control over its view. This is probably the more reliable approach.
Here is my solution.
presentViewController with no animation to avoid flash when present the alert controller.
[self presentViewController:alert animated:NO completion:^{
[alertController.view setTransform: CGAffineTransformMakeRotation(M_PI_2)];
}];
then create a UIAlertController category named e.g. UIAlertController+Orientation,
hide the view in viewWillDisappear to avoid flash back when dismiss the alert controller.
#import "UIAlertController+Orientation.h"
#implementation UIAlertController (Orientation)
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.view setHidden:YES];
}
- (BOOL) shouldAutorotate {
return NO;
}
#end
I am using XCode 5.1.1 for development purposes and using the iOS simulator to test my app.
I have an action sheet that has Save, Cancel and Delete options. I haven't yet coded the action handling for Save and Delete, but tapping on cancel should go back to the previous screen (I have used navigation controller to move between screens). But tapping on cancel, throws me "ViewController actionSheet:clickedButtonAtIndex:]: message sent to deallocated instance" error, which I am not able to solve. I have hooked up all the elements to their outlets/actions correctly. Below is my code. Please help. (I am trying to display the action sheet when a "return" button is clicked. And in the action sheet, when I tap cancel, the previous screen had to be displayed - I guess this can be done by dismissViewControllerAnimated which dismisses the current controller and displays the previous controller.)
-(IBAction)returnModalAction:(id)sender {
[self dismissViewControllerAnimated: YES completion: NULL];
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"What do you want to do with the user values?"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:#"Delete"
otherButtonTitles:#"Save", nil];
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:#"Cancel"];
[actionSheet showInView:self.view];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 2) {
NSLog(#"You have pressed the %# button", [actionSheet buttonTitleAtIndex:buttonIndex]);
}
}
On your method returnModalAction: you are dismissing the view, so the garbage collector will release all the references of self(the view controller) in memory that's why when you try to to show the action sheet [actionSheet showInView:self.view]; you get the error because the reference in memory doesn't exist.
So what you have to do is to perform [self dismissViewControllerAnimated: YES completion: NULL]; when you actually want to display the previous screen, in your case that would be on the actionSheet:clickedButtonAtIndex: method, based on the index of the button.
As my title said that clickedButtonAtIndex delegate method is call even tap on out side of UIActionSheet.
My actionSheet is display when I tapped on UIButton.
Code of my UIActionSheet declaration.
-(void)btnComplexityTapped:(UIButton *) sender
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Select your complexity" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Easy", #"Medium", #"High", nil];
[actionSheet showFromRect:sender.frame inView:self.view animated:YES];
[actionSheet release];
}
And in delegate method
- (void)actionSheet:(UIActionSheet *)myActionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)
{
[self.btnComplexity setTitle:#"Easy" forState:UIControlStateNormal];
}
else if(buttonIndex == 1)
{
[self.btnComplexity setTitle:#"Medium" forState:UIControlStateNormal];
}
else
{
[self.btnComplexity setTitle:#"High" forState:UIControlStateNormal];
}
}
I know that this issue is fix by set last condition in delegate method to set else if(buttonIndex == 1) instead of only else. But I does not want to apply any fixing but I want to know why delegate method is called even I am not tapping on any button of UIActionSheet
See this video for more clear picture.
As above video default title of button is "Medium" when I click on button then actionSheet is open and I click on out side of actionSheet (such like self.view) then delegate method clickedButtonAtIndex is called so last else condition is become true and thats way my button's title is changed "High".
Can any body tell my why this is happening ?
In iPad action sheet is presented in a popover. No cancel button because touching out of popover is equivalent to a touch on cancel. So, your delegate receives the message as if cancel button has been touch.
Because it is presented in POPOVER (iPad) which does not have cancel button on ActionSheet.Its Cancel is triggered if you tap out of ActionSheet.
I have a slide out menu in my app, which has a button that will display a UIActionSheet. This slide out menu just partly covers whatever view controller you previously were on.
- (void)cameraButtonPushed:(UIButton *)sender
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Create String" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Take Photo", #"Choose from Library", nil];
[actionSheet showInView:[UIApplication sharedApplication].keyWindow];
//[actionSheet showInView:self.parentViewController.view];
}
As you can see I have tried two ways of showing the action sheet and they both appear to work the same.
The problem that I'm having has to do with the action sheet buttons actually working. It shows up in the parent view controller (view controller that you were on), but if I press any of the buttons they do not work.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
EditVC *newEditVC = [self.storyboard instantiateViewControllerWithIdentifier:#"editVC"];
[editVC setHidesBottomBarWhenPushed:YES];
[self.parentViewController.navigationController pushViewController:newEditVC animated:YES];
//[self.navigationController pushViewController:newEditVC animated:YES];
} else if (buttonIndex == 1) {
EditVC *newEditVC = [self.storyboard instantiateViewControllerWithIdentifier:#"editVC"];
[editVC setHidesBottomBarWhenPushed:YES];
[self.parentViewController.navigationController pushViewController:newEditVC animated:YES];
//[self.navigationController pushViewController:newEditVC animated:YES];
}
}
Both of the above methods are in the same menu view controller where the button is pressed. I put some break points to test it out and the action sheet delegate method is being called. The if statement is working correctly, but the new VC's are not being pushed onto the navigation controller the way they should. It just runs over those lines and nothing happens. I have also tried setting it up in a way that parent view controller's also have the actionSheet:clickedButtonAtIndex: method in them, but that method is not called.
I believe that it has to do with setting up the actionSheet with an improper delegate, but I don't know for sure.
How can I call this action sheet from one view controller, display it and have actions performed in another? I have it appearing in the correct VC, but the action's aren't working.
I really have no idea how to do this. I created the UIActionSheet, it comes up when I tap a button, but I want, upon a certain option being selected for the app to segue to a new view controller.
You call in the UIActionSheetDelegate method (when the user taps the button) [self performSegueWithIdentifyer:#"segue_id"];
Use Delegate method of UIActionSheet (– actionSheet:clickedButtonAtIndex:)
#pragma mark - UIActionSheet Delegate Methods
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)
{
// code for Button 1
}
if(buttonIndex == 1)
{
// code for Button 2
}
}