UIAlertAction dismisses the UIAlertController in its callback [duplicate] - swift

This question already has answers here:
Prevent dismissal of UIAlertController
(5 answers)
Closed 8 years ago.
I am trying to use new UIAlertController introduced in iOS 8. Everything works great except the fact that UIAlertAction always end up dismissing the alert controller in its callback. Following is my code:
let alert = UIAlertController(title: "New Group", message: "Enter Group name", preferredStyle: UIAlertControllerStyle.Alert);
alert.addTextFieldWithConfigurationHandler({ [weak self] (nameField: UITextField!) in
nameField.becomeFirstResponder();
nameField.delegate = self;
return;
})
alert.addAction(UIAlertAction(title: "Done", style: .Default, handler: { action in
println("Done Entering");
}));
alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil));
self.presentViewController(alert, animated: true, completion: nil);
Now, when I click "Done" button, the controls enters the callback method and then alert is dismissed even though I don't have any statement to dismiss the alert. Is this behavior by default? If yes, how can I make sure that in some cases the alert stays on the screen (depending upon my conditions)? Am I missing something here?
I would really appreciate any help regarding this.

Yes, alert buttons always dismiss the alert and there is no way to configure them otherwise. If you want that behavior, you'll have to write your own alert. I've written SDCAlertView, which looks very much like a normal alert, but has some added functionality, including prevention of dismissing an alert when a button is tapped.
However, it doesn't use the UIAlertController API yet and it looks a little bit different (most users won't notice) on iOS 8 than the UIAlertController alert.
EDIT: It now has support for the UIAlertController-like API.

Related

Take a one time permission from user

I have a problem with taking permission from the users, my application is about the users ask and the app answers.
how can I make a pop-up window, when the user opens the application first time, the popup appears and ask for permission to save the question.
1. Display an alert view:
let alert = UIAlertController()
alert.title = "This is your title of the alert"
alert.message = "This is your question"
alert.addAction(UIAlertAction(title: "Answer one", style: .default , handler:{ (UIAlertAction)in
// Let's save the user's choice for later
UserDefaults.standard.set("UserChoseOptionOne", forKey: "myReallyImportantQuestion")
}))
alert.addAction(UIAlertAction(title: "Answer two", style: .default , handler:{ (UIAlertAction)in
// Let's save the user's choice for later
UserDefaults.standard.set("UserChoseOptionTwo", forKey: "myReallyImportantQuestion")
}))
alert.addAction(UIAlertAction(title: "Ask me later", style: .cancel, handler:{ (UIAlertAction)in
// Let's not do anything here.
// The user can't decide at the moment and let's ask the next time your app is opened again
}))
self.present(alert, animated: true, completion: nil)
2. In your viewDidLoad
// Here we have to differentiate between three cases!
// Case 1: This is the very first time our dear user opened our cool app
// or
// Case 2: This is not the first time, we already asked our important question and we have an answer already!
// or
// Case 3: This is not the first time, the last time we asked our question, the user decided to choose later. Later is now!
if let option = UserDefaults.standard.string(forKey: "myReallyImportantQuestion") {
// Here we handle Case 2. Maybe you don't want to do anything here
// We already have the user's choice saved in option
// We can do whatever we want with that
}else{
// Here are the cases 1 and 3.
// In here you can paste the code from "1. Display an alert view"
// If you feel fancy today, you can also make a function out of "1. Display an alert view" and call it in here
}
Create the userDefaults key
You now need to create a new static let called numberOfTimesLaunchedApp, this will be used to read and write to the userDefaults so that we can keep track of how many times the app has been opened

Disable the auto dismissal of the alert when tapping on a button

func showAlert(...) {
let alertController = UIAlertController(...)
let add = UIAlertAction(title: "Add", style: .default) { (action) in
onAdd?()
}
alertController.addAction(ok)
...
}
I would like to keep the popup alert after click on Add. But it seem iOS will auto close the popup. How to make it work?
The only way to prevent a UIAlertController's alert from being dismissed when a button is tapped is to disable the button.
If you don't like that, don't use UIAlertController; use your own presented view controller. That's all a UIAlertController is, after all. So it's easy to write your own if you need to.

Swift : OverlayView that appears at the bottom of the screen

I'd like to create a very common effect as in the picture below :
Explanation : the effect I'd like to accomplish consists in a view that appears (slides in) at the bottom of the screen when user clicks a button : you can still see the screen behind this view, but it applies a "dark layer" (black view with let's say 60% opacity) on the top of it. When user clicks on Block or Report absue (as for this example) it would perform the respective actions. Now when user clicks on cancel, and also when he clicks anywhere on the "dark layer" it would bring him back to the screen.
What I tried : presenting a new view controller (but it would use more data than necessary), using a overlay layer but I even didnt get close to that effect that we're usually seeing on apps. I'm not sure but I'd say that the best way to get that effect is using views ?
Does anyone have an idea please ?
Thanks and have a good day,
J
You are looking for a native element called UIActionSheet. It has become the part of UIAlertController, and does exactly what you are looking for.
Here is a little help how to set up one:
// Create you actionsheet - preferredStyle: .actionSheet
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
// Create your actions - take a look at different style attributes
let reportAction = UIAlertAction(title: "Report abuse", style: .default) { (action) in
// observe it in the buttons block, what button has been pressed
print("didPress report abuse")
}
let blockAction = UIAlertAction(title: "Block", style: .destructive) { (action) in
print("didPress block")
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in
print("didPress cancel")
}
// Add the actions to your actionSheet
actionSheet.addAction(reportAction)
actionSheet.addAction(blockAction)
actionSheet.addAction(cancelAction)
// Present the controller
self.present(actionSheet, animated: true, completion: nil)
It should produce the following output:

iOS 8 showFromToolbar effect with UIActionController

UIActionController replaced UIActionSheet in iOS 8. Is there any way to recreate the showFromToolbar behavior of UIActionSheet in UIActionController? This is the effect I am seeking. Please note though that I am trying to draw a UIActionController coming out of an external action bar button on an iPhone, so I couldn't do this using generic UIActionSheet example too I suppose.
I created a UIBarButtonItem and, in its IBAction I am creating a UIActionController. I tried the following:
var alert = UIAlertController(title: "XYZ", message: "XYZ", preferredStyle: .Alert
// Then created a bunch of UIAlertAction items and added them to alert
var popover = alert.popoverPresentationController
if popover != nil {
var s = sender as UIBarButtonItem
popover?.sourceView = s.customView
popover?.sourceRect = s.customView!.bounds
popover?.permittedArrowDirections = .Any
} else {
println("POPOVER is nil")
}
self.presentViewController(alert, animated: true, completion: nil)
However, this doesn't work with either iPhone or iPad simulators - the alert is showing in middle of screen and the above code always prints "POPOVER is nil". Even if it would have worked in iPad it wouldn't have solved my original problem. Your advice is appreciated.
Found this wonderful tutorial that explains how to do it.

Execute handler function after tap on UIAlertAction of UIAlertController *SpriteKit*

I am trying to get a UIAlterController to display (as soon as the scene is set up) with the following buttons:
Accept - won't do anything, just close the UIAlertController
Leave to Menu - should transition to the MenuScene
My code looks as follows (I put the alert controller inside an action so it first displays the scene and after 0.5 seconds it should start displaying the alert):
//make action
var actionBlock = SKAction.runBlock({
//alert controller
var alert = UIAlertController(title: "Welcome", message: "Are you sure you want to proceed?", preferredStyle: UIAlertControllerStyle.Alert)
//action with no handler
var acceptAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Cancel, handler: nil)
//action thats supposed to transition to MenuScene (AFTER BEING TAPPED!!)
var leaveAction = UIAlertAction(title: "Back to Menu", style: UIAlertActionStyle.Destructive, handler: {_ in self.backToMenu()})
//add action to the alert controller
alert.addAction(acceptAction)
alert.addAction(leaveAction)
//add alert controller to view
self.view?.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
}
//wait for 0.5s action
var wait = SKAction.waitForDuration(0.5)
//run the action
self.runAction(SKAction.sequence([wait, actionBlock]))
and I placed it right into the DidMoveToView function. When I run the code, it immediately transitions back to the MenuScene without even waiting for the user to tap either one of the actions, and then the alert is still on the screen (but on the MenuScene).
I am really confused and I've been on this for several hours but I just can't figure out what my mistake is, and how to make it work..
Anybody help please? Any code that works would be really appreciated!!!