dismiss UIAlertController presented by a modal view controller - ios

I seem to be running into a problem similar to one in an unresolved posted question: UIAlertController dismissing his presentingViewController
I am presenting a modal view controller on top of a normal UIViewController. Then I'm popping up an alert on that modal view controller. When I push "ok" to dismiss the alert (generated with the code below), the modal view controller is also dismissed.
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action{
[self dismissViewControllerAnimated: YES completion: nil];}];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Sign up problem."
message:#"Some fields are empty. Please check your inputs and try again."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:ok];
[self presentViewController:alert animated:YES completion:nil];
How can I dismiss just the alert?
I realize I can avoid this problem by using a navigation controller type setup instead and hiding the navigation bar, so I Get the same feel as the modal view controller, but this seems silly. Thanks.

Don't call self dismissViewController in the button handler. That specifically states that you want the view controller dismissed.
You don't need to dismiss the alert. It will automatically dismiss itself. The only thing you should do in the button handler is perform whatever action you need. Do nothing if you don't need to do anything.
If your alert is simply a message and you don't need to perform any action, just do this:
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil];

You don't need to dismiss or remove the UIAlertController manually in any way in a button handler - it does that itself.
Just remove the call to dismissViewControllerAnimated:completion:.

Related

Why is UIAlertController not pausing code while it waits for answer?

My understanding is that normal behavior for a UIAlertController after being presented is to wait for the user to respond in other words pause other code.
In this case when the user clicks save, a UIAlertController is supposed to appear, ask the user a question about saving and then wait for the response. However, the code is continuing and the alert controller gets dismissed after about one second.
What could be wrong with the following that is preventing the code from pausing and causing the alert to disappear after about one second?
-(void) save {
if (listView.text.length>=1) {
[self fireAlertNewOrUpdate];
}
// save everything else
//dismiss view controller - this line of code may be dismissing the alert controller...
}
-(void) fireAlertNewOrUpdate {
UIAlertController *listAlert = [UIAlertController alertControllerWithTitle:#"Save list as new?" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yes = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[self saveNewList];
}];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:#"Update existing" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action)
{
[self updateExisting];
}];
[listAlert addAction:cancel];
[listAlert addAction:yes];
if ([listAlert respondsToSelector:#selector(setPreferredAction:)]) {
[listAlert setPreferredAction:yes];
}
[self presentViewController:listAlert animated:YES completion:nil];
}
You've given the answer yourself, except that you've also hidden it from us. (Fortunately, you hinted at it in a comment.) It's because there's a line of code you've omitted, in save, where you dismiss the view controller. That view controller is the alert, so the alert appears in response to the call fireAlertNewOrUpdate and then immediately disappears again. In effect, you are saying present / dismiss in a single breath.
My understanding is that normal behavior for a UIAlertController after being presented is to wait for the user to respond in other words pause other code
No, not at all true. In fact, just the opposite. Your "other code" just goes right on even after the alert has appeared. There is basically nothing in iOS programming where code will spontaneously "pause". For this reason, it is quite usual after you call present to present a view controller to do nothing further in that code.

UIAlertController in wrong position

I have the situation where the alert is showing up in the upper left-hand corner of the screen (and cut off), as described in
UIAlertController is moved to buggy position at top of screen when it calls `presentViewController:`
My code is copy and paste from Apple's documentation:
- (void) alertHere
{
UIAlertController* alert = [UIAlertController
alertControllerWithTitle:#"My Alert"
message:#"This is an alert."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES
completion:nil];
}
I am calling this from a UIViewController.
I simply don't understand the stackoverflow discussion referenced above, nor the answers. I need something a poor simple programmer from steppes can understand.
Apple doesn't consider this a bug (apparently), but I don't understand why and I certainly don't understand how to fix it.
Thank you for a nice simple solution, or at least a simple description of what I'm doing wrong.
According to this post Attempt to present UIViewController on UIViewController whose view is not in the window hierarchy It seems you call alertHere from viewDidLoad so for solved your problem you must call it in ViewDidAppear.
The answer lies here: How to present UIAlertController when not in a view controller?
It took my a while to understand it, but once implemented, it works.

How can I implement the feature in my iOS app?

First Image: This view contains 2 navigation bar with tableview. In the second navigation bar, there is one button.
Second and Third Image: When I click on the navigation button (second) one view will appear like this screenshot and according to the selected title will change on navigation.
Again I I select click on the navigation button, again view will appear and when we select an option according to that option tableview will changes.
What is that pop-up view, how to add or show tableview in that view, how to achieve this feature using Objective-C?
The "popup view' in iOS is a UIAlertController: it has two subtypes: alert and action sheet. Then you need actions(those will represent each option in the actionsheet). Add each action to the action sheet then present it. Easy as that. Each action has a block that is executed when the action is selected. No need to show a tableCiew inside the actionsheet, it should stay as close to native as possible to keep the interface familiar to users. Refer to the human interface guidelines for more information.
UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:#"Title" message:#"Your message here" preferredStyle: UIAlertControllerStyleActionSheet ];
UIAlertAction *action = [UIAlertAction actionWithTitle:#"First item" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(#"first item pressed");
}];
[actionSheet addAction:action];
[self presentViewController:actionSheet animated:YES completion:nil];

If <UIAlertViewDelegate> is deprecated, how can I make my Alert button to do an action?

We used to use UIAlertViewDelegate in ViewController.h to make our custom Alert button to do an action, like pressing the Play Again button in the alert window makes the game restart.
How do we do this with UIAlertController, the replacement class for UIAlertView?
I read this document bellow provided by Apple and didn't see a delegate method mentioned. Does it mean we don't do that anymore?
https://developer.apple.com/reference/uikit/uialertcontroller
First add UIAlertController
Then Add UIAlertAction
Then add that action to your alert controller.
like below.
UIAlertController *myalert = [UIAlertController alertControllerWithTitle:#"your title" message:#"your messate" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *myaction = [UIAlertAction actionWithTitle:#"you title" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//your action here
}];
[myalert addAction:myaction];
[self presentViewController:myalert animated:YES completion:nil];
As it sounds like you found out, UIAlertView is deprecated (beginning in iOS 8), and so is UIAlertViewDelegate.
You're supposed to use UIAlertController instead. UIAlertController uses a different method for handling user taps on buttons. In UIAlertController you add UIAlertAction objects to your alert controller.
A UIAlertAction takes a block of code that gets called when the user triggers that action. Instead of setting up a delegate that listens for messages in a protocol, you pass a handler block (closure) to each button action that you set up. It's a different way of solving the same problem.
#AnuradhS gave sample code showing hot to set it up.

Replace button in UIActionSheet with UIView

I want to replace one of the buttons in my UIActionSheet with a UIView. I am integrating Facebook into my app, and the log in button (FBLoginView) is a subclass of UIView. I want use this view as a button in a UIActionSheet. Is this possible?
Edit: I am trying to integrate facebook sharing in my app. For that, i hacve to use their sdk. For logging into facebook, they provide their own custom made view called 'FBLoginView' which has been made as a subclass of UIView. I just have to allocate memory and add this view to my own view. Then clicking on the view will call all functions provided in the sdk, open the fb app or safari and ask for login and password etc. and then come back to the app.
Now I want to put this button in a UIActionSheet. In the sheet I don't see an option for customizing its buttons. Even if there was an option, how can I use the UIView to create UIButton?
It's not a good idea to mess around with UIActionSheet.
From UIActionSheet Class Reference:
Subclassing Notes
UIActionSheet is not designed to be subclassed, nor should you add views to its hierarchy. If you need to present a sheet with more customization than provided by the UIActionSheet API, you can create your own and present it modally with presentViewController:animated:completion:.
There are a quite a few action sheet replacements. Look at https://www.cocoacontrols.com/search?q=uiactionsheet for a starting list.
My suggestion is to find one with the features you like instead of hacking UIActionSheet.
I found this one from another user on StackOverflow, you might find it useful, as I did
Add UIView as subView on UIActionSheet
Good luck and let us know if you find any other solutions :)
UPDATE: I'd stay away from UIACtionSheet, as it's deprecated in iOS 8 onward. You need to use UIAlertController now. I'd use something like this:
UIAlertController * alert=[UIAlertController alertControllerWithTitle:#"Connection Method"
message:#"Select Connection Method"
preferredStyle:UIAlertControllerStyleActionSheet];
//These will essentially be the buttons that we used to create for UIActionSheet. They are created pretty much the same way as how they used to,
//but you have to declare their corresponding action here too.
UIAlertAction* firstAction = [UIAlertAction actionWithTitle:#"Title1"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
declaredVariable = NO;
[alert dismissViewControllerAnimated:NO completion:nil];
[self doSomethingHereOrExecuteTheFunctionYouNeed];
}];
UIAlertAction* secondAction = [UIAlertAction actionWithTitle:#"Title2 and so on"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
BOOL newVarable = YES;
[alert dismissViewControllerAnimated:NO completion:nil];
[self followAlertControllerChoice];
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:#"Cancel button"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
[alert dismissViewControllerAnimated:YES completion:nil];
}];
//Add buttons ("Actions") here
[alert addAction:firstAction];
[alert addAction:secondAction];
[alert addAction:cancel];
//Finally, present your alertcontroller
[self presentViewController:alert animated:YES completion:nil];
AFAIK, you can only add textfields to the alertcontroller, and you can do it like this:
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = #"Enter your text here";
textField.textAlignment = NSTextAlignmentLeft;
//So On so forth
}];
Apparently, Apple doesn't want us to subclass the UIAlertController, per here:
The UIAlertController class is intended to be used as-is and does not
support subclassing. The view hierarchy for this class is private and
must not be modified.

Resources