How to prevent SegmentedControl index from changing, based upon confirmation dialog box? - ios

I have a SegmentedControl. When the user clicks on it, a confirmation dialog box appears, asking if they wish to change the value. If they click "Cancel", I want to cancel the change to the SegmentedControl value.
This is a code segment I have:
#IBAction func indexChanged(_ sender: UISegmentedControl) {
let refreshAlert = UIAlertController(title: "Update", message: "Sure you wanna change this?", preferredStyle: UIAlertControllerStyle.alert)
refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in
}))
refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action: UIAlertAction!) in
// Nothing
}))
present(refreshAlert, animated: true, completion: nil)
}
Thanks in advance.

The best way is to keep a variable that holds the last selected index. On completion handler of cancel , set your segment's selected index to the variable's value. On Ok's completion handler update the variable with the current selected index.

Related

How to pass multiple handlers in UIAlertAction

I've few buttons, clicking on these buttons present same alert. I've to handle each button click separately so I need to pass different handlers to each of these alerts. How do I do it?
I've searched for solutions but I can't find what I'm looking for, or may be It's there but I'm not able to understand it.
Following is my code snippet. Inside this function I can get which button is clicked but I'm not able to figure out how to call different handlers and pass them alert.title.
I hope someone can point me in right direction.
#IBAction func buttonClicked(_ sender: UIButton) {
let alert = UIAlertController(title: "Select Value", message: nil, preferredStyle: .actionSheet)
for list in self.listValue {
alert.addAction(UIAlertAction(title: list.value, style: .default, handler: { _ in
// How do I call different handlers here?
// I'll need to retrieve alert.title in these handlers
}))
}
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
self.present(alert, animated: false, completion: nil)
}
It's not totally clear what you're asking, but if you are trying to figure out which button was pressed so that you can execute different methods for each one you can do something like this:
#IBAction func buttonClicked(_ sender: UIButton) {
let alert = UIAlertController(title: "Select Value", message: nil, preferredStyle: .actionSheet)
for list in self.listValue {
alert.addAction(UIAlertAction(title: list.value, style: .default, handler: { (action) in
// How do I call different handlers here?
// I'll need to retrieve alert.title in these handlers
switch action.title {
case "Value A":
print("It's Value A")
case "Value B":
print("It's Value B")
default:
print("We didn't implement anything for this value")
}
}))
}
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
self.present(alert, animated: false, completion: nil)
}

Swift: UITextField is not being recognized

I want the user to press a button, and then for them to be able to see an alert where they can enter an input (to set a price for a service). The other logic involves saving data to a database, which is not really relevant to my problem.
I am using the following example:
https://stackoverflow.com/a/30139623/2411290
It definitely works, in that it shows the alert correctly, but once I include
print("Amount: \(self.tField.text)")
"self.tField.text" is not recognized. The specific error I get is:
value of type 'testVC' has no member 'tField'
#IBAction func setAmount(_ sender: Any) {
var tField: UITextField!
func configurationTextField(textField: UITextField!)
{
print("generating textField")
textField.placeholder = "Enter amount"
tField = textField
}
func handleCancel(alertView: UIAlertAction!)
{
print("Cancelled")
}
let alert = UIAlertController(title: "Set price of service", message: "", preferredStyle: .alert)
alert.addTextField(configurationHandler: configurationTextField)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler:handleCancel))
alert.addAction(UIAlertAction(title: "Done", style: .default, handler:{ (UIAlertAction) in
print("Done !!")
}))
self.present(alert, animated: true, completion: {
print("completion block")
print("Amount: \(self.tField.text)") // Error here
})
//// other logic for app
}
tField is a local variable inside your setAmount function. It is not a property of the class.
Change:
self.tField.text
to:
tField.text
That will allow you to access the local variable.
But the real question is why are you creating a local variable of UITextField inside this function? Why are you printing its text when the text field isn't used anywhere?
Most likely you should be accessing the alert's text field inside the action handler for the "Done" button. There's no need to do anything inside the completion block of presenting the alert.
#IBAction func setAmount(_ sender: Any) {
let alert = UIAlertController(title: "Set price of service", message: "", preferredStyle: .alert)
alert.addTextField(configurationHandler: { (textField) in
print("generating textField")
textField.placeholder = "Enter amount"
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { (action) in
print("Cancelled")
})
alert.addAction(UIAlertAction(title: "Done", style: .default) { (action) in
print("Done !!")
if let textField = alert.textFields?.first {
print("Amount: \(textField.text)")
}
})
self.present(alert, animated: true, completion: nil)
}
My guess is that when you present an alert your current ViewController is the alert viewController... And in your alert there is no variable tField.
On the exampled you quoted the alert was presented only after the print with tField's value. That why that worked there and doesn't work in your case.

UIAlertController Keeps Re-Appearing After Closing It

I have written code for an alert to appear when the input in one of my UITextFields is less than 1050. It successfully appears when the inputs satisfies that, but after I press "OK" it instantly re-appears.
Below is the code in the viewDidLoad function:
override func viewDidLoad(){
super.viewDidLoad()
alert = UIAlertController(title: "Error", message: "Please enter an exit width value greater than 1050", preferredStyle: UIAlertControllerStyle.Alert)
let okay = UIAlertAction(title: "OK", style: UIAlertActionStyle.Destructive, handler: valueCalc)
alert.addAction(okay)
}
Then I have in my valueCalc function (which is called when a button is tapped):
#IBAction func valueCalc(sender: AnyObject){
if(Int(mmText.text!)! < 1050){ //mmText is an UITextField
self.presentViewController(alert, animated: true, completion: nil)
}
}
According to your line of code
let okay = UIAlertAction(title: "OK", style: UIAlertActionStyle.Destructive, handler: valueCalc)
Your handler name valueCalc is called when you press OK.
Again the value is calculated which when come out be less then the specified characters shows back you the alert.
Instead of that, replace this line in your code -
let okay = UIAlertAction(title: "OK", style: UIAlertActionStyle.Destructive, handler: handlerMethod)
and add this method to your code
func handlerMethod() {
//handle your action here after ok is pressed for e.g if you wanna just dismiss the alert then write
dismissViewControllerAnimated(true, completion: nil)
}
You have the handler argument for your UIAlertAction set to valueCalc. Therefore, whenever the user taps "OK", the method valueCalc gets run again, and since the value is (presumably) still the same, the alert is presented right back again.
Try this
override func viewDidLoad(){
super.viewDidLoad()
alert = UIAlertController(title: "Error", message: "Please enter an exit width value greater than 1050", preferredStyle: UIAlertControllerStyle.Alert)
let okay = UIAlertAction(
title: "OK",
style: UIAlertActionStyle.Destructive) { (action) in }
}
#IBAction func valueCalc(sender: AnyObject){
if(Int(mmText.text!)! < 1050){ //mmText is an UITextField
self.presentViewController(alert, animated: true, completion: nil)
}

How to change Action Sheet Default action color only?

I have an Action Sheet with one Default action and one Cancel action. How can I change just Default action text color?
var refreshAlert = UIAlertController(title: "", message: "Are you sure you want to clear the entire message history? \n This cannot be undone.", preferredStyle: UIAlertControllerStyle.ActionSheet)
refreshAlert.addAction(UIAlertAction(title: "Clear message history", style: .Default, handler: { (action: UIAlertAction!) in
print("Handle Ok logic here")
// how to change this text color to red?
}))
refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: { (action: UIAlertAction!) in
print("Handle Cancel Logic here")
}))
You cannot. Instead Change your method like below: Apple has provided red color for Destructive buttons.
refreshAlert.addAction(UIAlertAction(title: "Clear message history", style: .Destructive, handler: { (action: UIAlertAction!) in
print("Voila !! button color is changed")
}))
I don't think there is a direct way to do that. However, there is bit of an ugly trick you can apply here:
Create an image of exactly same size as that of UIAlertController action sheet style button.
Make sure image looks like exactly same as that you want your UI to look like including text & colour.
Pass that image as image property of your Default action like this:
->
let defaultAction = UIAlertAction(title: "Clear message history", style: .Default, handler: { (action: UIAlertAction!) in
print("Handle Ok logic here")
// how to change this text color to red?
})
let image = UIImage(named: "myButtton.png")
defaultAction.setValue(image, forKey: "image")
alertController.addAction(defaultAction)

Swift: UIAlertController select subset from list

I have a button that causes a UIAlertController to appear. I want to show a couple choices to the user and allow them to select a subset of the options.
[A +]
[B ]
[C +]
[D ]
[----]
[DONE]
I need to give an array to fill the options and then let the users select their subset (+ symbols in this example -> likely more common to use check marks). When they click done then it would let the code know their selection. Here is my current code from the button segue.
#IBAction func insideButton(sender: AnyObject) {
var refreshAlert = UIAlertController(title: "Refresh", message: "All data will be lost.", preferredStyle: UIAlertControllerStyle.Alert)
refreshAlert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { (action: UIAlertAction!) in
print("Handle Ok logic here")
}))
refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .Default, handler: { (action: UIAlertAction!) in
print("Handle Cancel Logic here")
}))
presentViewController(refreshAlert, animated: true, completion: nil)
}
How would I do this?
From the UIAlertController docs: "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."
You'll have to make your own custom alert and present it.

Resources