I am setting up the UIAlertController in this way:
this implementation is done in viewDidLoad -
actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
actionButton1 = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionButton2 = UIAlertAction(title: " Resend", style: .default) {
action in
self.resendCode()
}
actionButton2.setValue(UIImage(named: "MailForActionSheet"), forKey: "image")
actionButton2.setValue(0, forKey: "titleTextAlignment")
actionSheet.addAction(actionButton1)
actionSheet.addAction(actionButton2)
I've set title and message as nil because I want no header in the action sheet.
The function resendCode tries to modify the action sheet in this way (implemented in the same viewcontroller):
func resendCode()
{
actionButton2.isEnabled = false
actionSheet.title = "Resending Code not be done again"
actionSheet.message = ""
}
However all I see is blank title and message (header is now present). What's wrong here and how should I correct this?
Before:
After:
edit:
Action sheet is presented on click of a button
present(actionSheet, animated: true, completion: nil)
Related
I have a signup screen with a phone number field.
If the user type a too short phone number, I display an UIAlertController.
After she dismisses the Alert, the user can't send her phone number again as the send button is tapped.
Is there a way to reload the view when the alert is dismissed to make the button untapped?
Thanks
func present_alert(title:String, content : String){
let myAlert = UIAlertController(title:title, message:content, preferredStyle:UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler:nil)
myAlert.addAction(okAction)
self.present(myAlert, animated:true)
}
the main reason on button click you disabled the yourbutton sender.isEnabled = false, when ever the alert is presented again enable your button , surely works addyourbuttonName.isEnabled = true
if you want to clear the current textfield value then use yourtextfield.text = ""
let alertController = UIAlertController(title: “Simple”, message: “Simple alertView demo with Cancel and Ok.”, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: “OK”, style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
print(“OK”)
yourtextfield.text = ""
yourtextfield.becomeFirstResponder()
addyourbuttonName.isEnabled = true
}
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
func present_alert(title:String, content:String, button:UIButton){
let myAlert = UIAlertController(title:title, message:content, preferredStyle:UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler:nil)
myAlert.addAction(okAction)
self.present(myAlert, animated:true){
button.isEnabled = true
}
}
As i understand your issue the problem is that you receive your button false value of parameter "isEnabled". To fix that just add to your block last string:
buttonName.isEnabled = true
After click on UIAlertAction(cancel or ok), you can add some functionality in that ok or cancel method. In the final step of that method, add viewWillAppear(true) method. Then UIViewController automatically refresh.
Please help! Im a huge beginner. Im trying to get a picker view and a textfield into one alert controller. Apparently I can't add a picker view into an alert controller since IOS 8. Instead I need to use an action sheet with multiple actions. Why can't I use a default alert style? Because I need more than 2 actions and the default alert style apparently only permits a max of 2 actions. So, I need to use an action sheet. Only problem is I can't seem to find a way to put an editable textfield into an action sheet, to have multiple action options - instead of an editable textfield in my default alert style, with only two action options.
This is what I have so far, for my editable textfield in my default alert style, with only two options (OK and cancel):
#IBOutlet weak var TEXTTESTLabel: UILabel!
#IBAction func TEXTESTTapped(_ sender: UIButton) {
print("TEXTTEST Button Tapped")
openTEXTTESTAlert()
}
func openTEXTTESTAlert() {
//Create Alert Controller
let alert9 = UIAlertController (title: "Test Your Text:", message: nil, preferredStyle: UIAlertControllerStyle.alert)
//Create Cancel Action
let cancel9 = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
alert9.addAction(cancel9)
//Create OK Action
let ok9 = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (action: UIAlertAction) in print("OK")
let textfield = alert9.textFields?[0]
print(textfield?.text!)
self.TEXTTESTLabel.text = textfield?.text!
}
alert9.addAction(ok9)
//Add Text Field
alert9.addTextField { (textfield: UITextField) in
textfield.placeholder = "TEXTTEST"
}
//Present Alert Controller
self.present(alert9, animated:true, completion: nil)
}
//////////////////////////////////////////////////////////////////////////////////
Since this, I've gotten help to create two separate alert controllers but it looks and feels messy. It's set up so if I click button 2 the default alert style with a textfield will pop and insert text into a label. But, if i click button 1, AND THEN I click button 2, it will show an action sheet with 4 actions that put a word into that same label. This is what I have for that method:
#IBOutlet weak var TextLabel: UILabel!
var userWantsToShowAlert = false
#IBAction func yourNewButtonTapped(_ sender: UIButton) {
userWantsToShowAlert = !userWantsToShowAlert
print("User wants to show alert? \(userWantsToShowAlert)")
//This is userWantsToShowAlert is false, it will change it to true. And if it is true, it will change it to false.
}
#IBAction func TextButtonTapped(_ sender: UIButton) {
print("Text Button Tapped")
if(userWantsToShowAlert){
openTextAlert()
}else{
openActionSheetAlert()
}
}
func openTextAlert() {
//Create Alert Controller
let alert9 = UIAlertController (title: "Whatever Text Your Heart Desires:", message: nil, preferredStyle: UIAlertControllerStyle.alert)
//Create Cancel Action
let cancel9 = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
alert9.addAction(cancel9)
//Create OK Action
let ok9 = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (action: UIAlertAction) in print("OK")
let textfield = alert9.textFields?[0]
print(textfield?.text!)
self.TextLabel.text = textfield?.text!
}
alert9.addAction(ok9)
//Add Text Field
alert9.addTextField { (textfield: UITextField) in
textfield.placeholder = "Whatever text you want to enter"
}
//Present Alert Controller
self.present(alert9, animated:true, completion: nil)
}
func openActionSheetAlert(){
let alert9 = UIAlertController (title: "Whatever Text Your Heart Desires:", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
//Create Cancel Action
let cancel9 = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
alert9.addAction(cancel9)
let bt1 = UIAlertAction(title: "1", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 1"}
alert9.addAction(bt1)
let bt2 = UIAlertAction(title: "2", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 2"}
alert9.addAction(bt2)
let bt3 = UIAlertAction(title: "3", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 3"}
alert9.addAction(bt3)
let bt4 = UIAlertAction(title: "4", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 4"}
alert9.addAction(bt4)
alert9.popoverPresentationController?.sourceView = self.view
alert9.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.size.width / 2.0, y: self.view.bounds.size.height / 4.0, width: 1.0, height: 1.0)
self.present(alert9, animated:true, completion: nil)
}
I find that this method is confusing to the application user. If anyone has a different method to get a textfield into an action sheet (or even a separate alert controller imbedded in a current alert controller), I'd appreciate it VERY much!
Thank you :)
For Action sheet you can use as
func showActionSheet()
{
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
actionSheet.addAction(UIAlertAction(title: "1:", style: UIAlertActionStyle.default, handler: { (alert:UIAlertAction!) -> Void in
)
self.action1()
}))
actionSheet.addAction(UIAlertAction(title: "2", style: UIAlertActionStyle.default, handler: { (alert:UIAlertAction!) -> Void in
self.action2()
}))
actionSheet.addAction(UIAlertAction(title: "3", style: UIAlertActionStyle.default, handler: { (alert:UIAlertAction!) -> Void in
// self.action3()
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
// showActionSheet()
I found the solution! I was wrong about having only 2 actions in the default alert style. How to scroll through actions in alert controller? Xcode 8, Swift 3, IOS
My view is being dismissed through the previous button on the navigation bar. I think the correct term for that is that the view is being popped off the view stack. Now before actually dismissing the view I want to display a UIAlert asking the user to setup his/her address.
I've tried this but the UIAlert is not being show:
override func viewWillDisappear(animated: Bool) {
if let currentUser = ApiManager.sharedInstance.currentUser {
if !currentUser.hasAddress {
let alert = UIAlertController(title: "Missing address", message: "We see you're stilling missing an address, would you like set it now?", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "yes".localized, style: .Default, handler: { (alertAction) in
let newViewController = LocationViewController()
newViewController.delegate = self
self.navigationController?.pushViewController(newViewController, animated: true)
}))
alert.addAction(UIAlertAction(title: "no".localized, style: .Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
In my console the following gets printed:
2016-10-28 16:58:47.380 gaifong[17096:14515422] Warning: Attempt to present <UIAlertController: 0x7fd7037e4cb0> on <gaifong.ProfileViewController: 0x7fd7048cc000> whose view is not in the window hierarchy!
You should add leftBarButtonItem on navigationItem and make an action to leftBarButtonItem where you can handle this.
in viewDidLoad
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(self.goBack))
// Then handle the button selection
func goBack() {
if let currentUser = ApiManager.sharedInstance.currentUser {
if !currentUser.hasAddress {
let alert = UIAlertController(title: "Missing address", message: "We see you're stilling missing an address, would you like set it now?", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "yes".localized, style: .Default, handler: { (alertAction) in
// here you can pop to main controller
self.navigationController?.popViewControllerAnimated(true)
}))
alert.addAction(UIAlertAction(title: "no".localized, style: .Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
I am trying to popViewController to the previous View Controller in the navigation stack after an alertView. As of now, my program will not run the popViewController method, since the alertView is in the way, and brings up the error:
UINavigationController 0x17670900 while an existing transition or presentation is occurring; the navigation stack will not be updated.
How do I go about running the popViewController method after the user clicks OK from the alertView? Do I have to set a delegate which detects when the used clicks OK?
Here is my code:
//alertView after Picture saved
let alertView = UIAlertController(title: "Success!", message: "Record Saved to Database", preferredStyle: .Alert)
alertView.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
self.presentViewController(alertView, animated: true, completion: nil)
//go to previous controller using popViewController, doesnt work, brings up error message
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
You need to pop the view controller when user presses the Ok button from AlertView.
let alertView = UIAlertController(title: "Success!", message: "Record Saved to Database", preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "Ok", style: .Default) { (action) in
// pop here
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
}
alertView.addAction(OKAction)
self.present(alertView, animated: true, completion: nil)
You can put the "popViewControllerAction" inside an alert action like this.
func alertMethod() {
var okAlertController = UIAlertController(title: NSLocalizedString("Your title", comment: ""), message: "Your message", preferredStyle:
UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: NSLocalizedString("Ok", comment: ""), style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
// your action - navController.popViewControllerAnimated(true)
}
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
// your action
}
}
saveAlertController.addAction(okAction)
saveAlertController.addAction(cancelAction)
self.presentViewController(okAlertController, animated: true, completion: nil)
}
That should work, in that case the method gets called after the user presses a button...
I have no idea how to change screens programatically. I have an alert view and I want to be able to change screen when the user presses the "Ok" button. How do I do this?
Here is my new code:
func showAlertController(){
let tilte = "My Medication"
let message = NSLocalizedString("Go through Medication guide?", comment: "")
let cancelButtonTitle = NSLocalizedString("Dismiss", comment: "")
let otherButtonTitle = NSLocalizedString("Ok", comment: "")
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel){ action in
NSLog("User said no")}
let otherAction = UIAlertAction(title: otherButtonTitle, style: .Default){action in
// I know I need to put something in here.
let appointment = Appointment()
self.presentViewController(appointment, animated:true, completion:nil)
}
alertController.addAction(cancelAction)
alertController.addAction(otherAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
However now I get a bug saying:
Thread 1: EXC_BAD_INSTRUCTION(code=EXC_l1386_INVOP,subcode=0x0)
Add presentViewController inside UIAlertAction closure for "Ok" button, it means that the button is pressed and so you do your stuffs for the button being pressed inside the block.
class MainViewController: UIViewController {
...
...
func showAlertController(){
let tilte = "My Medication"
let message = NSLocalizedString("Go through Medication guide?", comment: "")
let cancelButtonTitle = NSLocalizedString("Dismiss", comment: "")
let otherButtonTitle = NSLocalizedString("Ok", comment: "")
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel){ action in
NSLog("User said no")}
let otherAction = UIAlertAction(title: otherButtonTitle, style: .Default){action in
// I know I need to put something in here.
let appointmentViewController = AppointmentViewController()
self.presentViewController(appointmentViewController, animated:true, completion:nil)
}
alertController.addAction(cancelAction)
alertController.addAction(otherAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
...
...
}
class AppointmentViewController: UIViewController {
}