I'm trying to add some actions to a UIAlertController but I am getting an error when I'm passing it a closure. I want to pass that closure as a handler for an action, but I am getting an error message.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let optionMenu = UIAlertController(title: nil, message: "What do you want to do?", preferredStyle: .ActionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
optionMenu.addAction(cancel)
self.presentViewController(optionMenu, animated: true, completion: nil)
let callActionHandler = { (action:UIAlertAction) -> Void in
let alertMessage = UIAlertController(title: "No service", message: "Sorry the phone option is not working right now, try again later", preferredStyle: .Alert)
alertMessage.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
self.presentViewController(alertMessage, animated: true, completion: nil)
}
let callAction = UIAlertAction(title: "Call " + "123-000-\(indexPath.row)", style: UIAlertActionStyle.Default , handler: callActionHandler)
optionMenu.addAction(callAction)
}
Solved. Only ! you missed.
Change the below line
let callActionHandler = { (action:UIAlertAction) -> Void in
with
let callActionHandler = { (action:UIAlertAction!) -> Void in
That's it !
Related
I am trying to modulraise my code I am able to create extension for alertController without target
extension UIViewController {
func showAlert(title: String, message: String) {
let alertController = UIAlertController(title: title, message:
message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: {_ in
}))
self.present(alertController, animated: true, completion: nil)
}
}
but I am not sure how to create extension which have target and textfield(how to create and call that in viewcontroller)
my code for which i am trying to create extension
let alertController = UIAlertController(title: "enter name", message: nil, preferredStyle: .alert)
let addAction = UIAlertAction(title: "Ok", style: .default) {_ in
guard let name = alertController.textFields?.first?.text else { return }
let newTask = Task(name: name)
self.toDoStore?.add(newTask, at: 0)
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.insertRows(at: [indexPath], with: .automatic)
}
addAction.isEnabled = false
let cancelAction = UIAlertAction(title: CANCEL_ACTION, style: .cancel, handler: nil)
alertController.addTextField { textField in
textField.placeholder = "enter name.."
textField.addTarget(self, action: #selector(self.handleTextChanged), for: .editingChanged)
}
alertController.addAction(addAction);
alertController.addAction(cancelAction);
present(alertController, animated: true, completion: nil)
You could try the below extension that I'm using made a few changes according to your requirements.
extension UIViewController {
func showAlert(_ title: String?,
message: String?,
actions: [String: UIAlertAction.Style] = [:],
handler: ((UIAlertAction) -> Void)? = nil,
textFields: [((UITextField) -> Void)] = []) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
if actions.isEmpty {
alert.addAction(UIAlertAction(title: "Okay", style: .default))
} else {
for action in actions {
alert.addAction(UIAlertAction(title: action.key, style: action.value, handler: handler))
}
}
for textField in textFields {
alert.addTextField(configurationHandler: textField)
}
present(alert, animated: true)
}
}
A bit of advise you can always check how the parameters that you pass are accepted by the system API and customize your own function in a similar way.
Hey guys so I'm doing registration form with Swift 4 and using Firebase.
I'm stuck on reseting the password. Whenever I click on the button "forget password" I should get a pop up window with textField to fill in my email address. But when I do click nothing happens. Posting code below if anyone have some ideas what can be wrong with it
#IBAction func forgotPasswordTapped(_ sender: Any) {
let forgotPasswordAlert = UIAlertController(title: "Forgot password?", message: "Enter email address", preferredStyle: .alert)
forgotPasswordAlert.addTextField { (textField) in
textField.placeholder = "Enter email address"
}
forgotPasswordAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
forgotPasswordAlert.addAction(UIAlertAction(title: "Reset Password", style: .default, handler: { (action) in
let resetEmail = forgotPasswordAlert.textFields?.first?.text
Auth.auth().sendPasswordReset(withEmail: resetEmail!, completion: { (error) in
if error != nil{
let resetFailedAlert = UIAlertController(title: "Reset Failed", message: "Error: \(String(describing: error?.localizedDescription))", preferredStyle: .alert)
resetFailedAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetFailedAlert, animated: true, completion: nil)
}else {
let resetEmailSentAlert = UIAlertController(title: "Reset email sent successfully", message: "Check your email", preferredStyle: .alert)
resetEmailSentAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetEmailSentAlert, animated: true, completion: nil)
}
})
}))
}
As a quick answer, you are simply forgetting to present your forgotPasswordAlert. The fix is simple:
#IBAction func forgotPasswordTapped(_ sender: Any) {
let forgotPasswordAlert = UIAlertController(title: "Forgot password?", message: "Enter email address", preferredStyle: .alert)
forgotPasswordAlert.addTextField { (textField) in
textField.placeholder = "Enter email address"
}
forgotPasswordAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
forgotPasswordAlert.addAction(UIAlertAction(title: "Reset Password", style: .default, handler: { (action) in
let resetEmail = forgotPasswordAlert.textFields?.first?.text
Auth.auth().sendPasswordReset(withEmail: resetEmail!, completion: { (error) in
if error != nil{
let resetFailedAlert = UIAlertController(title: "Reset Failed", message: "Error: \(String(describing: error?.localizedDescription))", preferredStyle: .alert)
resetFailedAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetFailedAlert, animated: true, completion: nil)
}else {
let resetEmailSentAlert = UIAlertController(title: "Reset email sent successfully", message: "Check your email", preferredStyle: .alert)
resetEmailSentAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetEmailSentAlert, animated: true, completion: nil)
}
})
}))
//PRESENT ALERT
self.present(forgotPasswordAlert, animated: true, completion: nil)
}
As a small aside, you'll want to make sure you are presenting your confirmation alerts on the main queue to avoid unexpected behavior. Perhaps the sendPasswordReset does this automatically, but I do not believe this to be the case. Additionally, the better way of getting the error description to present to the user is with optional binding (using if let).
Auth.auth().sendPasswordReset(withEmail: resetEmail!, completion: { (error) in
//Make sure you execute the following code on the main queue
DispatchQueue.main.async {
//Use "if let" to access the error, if it is non-nil
if let error = error {
let resetFailedAlert = UIAlertController(title: "Reset Failed", message: error.localizedDescription, preferredStyle: .alert)
resetFailedAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetFailedAlert, animated: true, completion: nil)
} else {
let resetEmailSentAlert = UIAlertController(title: "Reset email sent successfully", message: "Check your email", preferredStyle: .alert)
resetEmailSentAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetEmailSentAlert, animated: true, completion: nil)
}
}
})
For swift 4.2
import Firebase
// MARK: Firebase Forgotpassword
func callFIRPasswordReset(){
//show loader
Auth.auth().sendPasswordReset(withEmail: self.txtEmail.text!) { (error) in
DispatchQueue.main.async {
//hide loader
self.txtEmail.text = ""
if let error = error {
//show alert here
print(error.localizedDescription)
}
else {
//show alert here
print("We send you an email with instructions on how to reset your password.")
}
}
}
}
I wanna add message to phone call alert popup.
how to make it?
enter image description here
Yes, you can do it like that:
func phoneCall(to phoneNumber:String) {
if let callURL:URL = URL(string: "tel:\(phoneNumber)") {
let application:UIApplication = UIApplication.shared
if (application.canOpenURL(callURL)) {
let alert = UIAlertController(title: "Your Title", message: "Do you want call that number?", preferredStyle: .alert)
let callAction = UIAlertAction(title: "Call", style: .default, handler: { (action) in
application.openURL(callURL)
})
let noAction = UIAlertAction(title: "No", style: .cancel, handler: { (action) in
print("Canceled Call")
})
alert.addAction(callAction)
alert.addAction(noAction)
self.present(alert, animated: true, completion: nil)
}
}
}
I am going to use UIAlertController for a user to select one item.
The items to select are array as following:
let arraySelect = ["NewYork", "Washington", "Seoul", "Tokyo", "Peking", "Sidney", ... ]
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .Alert)
// Add items in array to Alert
for var i = 0; i < arraySelect.count; i++ {
alert.addAction(UIAlertAction(title: arrayBibleVersions[i], style: .Default, handler: {(_) in }))
}
// Add cancel button.
alert.addAction(UIAlertAction(title: "취소", style: .Cancel, handler: {(_) in }))
self.presentViewController(alert, animated: false, completion: nil)
When a user touched one item, I have to get the index of the item that a user toched on.
But I don't know how to get the index..
Please help me.
I solved my question as following:
let arraySelect = ["NewYork", "Washington", "Seoul", "Tokyo", "Peking", "Sidney", ... ]
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .Alert)
let closure = { (action: UIAlertAction!) -> Void in
let index = alert.actions.indexOf(action)
if index != nil {
NSLog("Index: \(index!)")
}
}
for var i = 0; i < arrayBibleVersions.count; i++ {
alert.addAction(UIAlertAction(title: arrayBibleVersions[i][1], style: .Default, handler: closure))
}
alert.addAction(UIAlertAction(title: "cancel", style: .Cancel, handler: {(_) in }))
self.presentViewController(alert, animated: false, completion: nil)
This is how I solved it in Swift 4 / iOS11
projects.forEach { project in
alertController.addAction(
UIAlertAction(title: project.name, style: .default, handler: { action in
if let index = alertController.actions.index(where: { $0 === action }) {
self.showProject(project: projects[index])
}
})
)
}
I have the same problem too and found the method below which saved me.
But be careful if the item in array are the same, it will return the first item's index.
Fortunately, It's work in this case, because we create the action and using action to search.
extension Array where Self.Element : Equatable {
...
#inlinable public func index(of element: Element) -> Int?
...
}
It work in Swift 4
let arraySelect = ["NewYork", "Washington", "Seoul", "Tokyo", "Peking", "Sidney"]
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
// Add items in array to Alert
for name in arraySelect {
alert.addAction(UIAlertAction(title: name, style: .default, handler: {(action) in
// print idx that user selected
if let idx = alert.actions.index(of: action) {
print("idx = \(idx)")
}
}))
}
// Add cancel button.
alert.addAction(UIAlertAction(title: "취소", style: .cancel, handler: {(_) in }))
self.present(alert, animated: true, completion: nil)
This is working good:
var arraySelect = ["NewYork", "Washington", "Seoul", "Tokyo", "Peking", "Sidney"]
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .Alert)
let closure = { (action: UIAlertAction!) -> Void in
let index = alert.actions.indexOf(action)
if index != nil {
NSLog("Index: \(index!)")
}
}
for field in arraySelect {
alert.addAction(UIAlertAction(title: field, style: .Default, handler: closure))
}
alert.addAction(UIAlertAction(title: "cancel", style: .Cancel, handler: {(_) in }))
self.presentViewController(alert, animated: false, completion: nil)
Block is executed when the user selects a action.
// Add cancel button.
alert.addAction(UIAlertAction(title: "취소", style: .Cancel, handler: {(_) in
//your code
}))
func FirefoxAhri(){
let optionMenu = UIAlertController(title: "title", message: "message", preferredStyle: UIAlertControllerStyle.ActionSheet)
let action1 = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Destructive){
action -> Void in
//do stuff on click Yes
}
let action2 = UIAlertAction(title: "No", style: UIAlertActionStyle.Destructive){
action -> Void in
//do stuff on click No
}
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
print("Cancel")
// do nothing if you don't want. alert closes automatically
}
optionMenu.addAction(action1)
optionMenu.addAction(action2)
optionMenu.addAction(cancelAction)
self.presentViewController(optionMenu, animated: true, completion: nil)
}
In one of my viewController, I want to make an alert box appear that prompts the user to type this information.Then, I want the user to store this input using NSUserDefaults. How can I achieve this?
Thank you in advance!
Check this out:
let alertController = UIAlertController(title: "Email?", message: "Please input your email:", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (_) in
guard let textFields = alertController.textFields,
textFields.count > 0 else {
// Could not find textfield
return
}
let field = textFields[0]
// store your data
UserDefaults.standard.set(field.text, forKey: "userEmail")
UserDefaults.standard.synchronize()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
alertController.addTextField { (textField) in
textField.placeholder = "Email"
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
SWIFT 3
func presentAlert() {
let alertController = UIAlertController(title: "Email?", message: "Please input your email:", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (_) in
if let emailTextField = alertController.textFields?[0] {
// do your stuff with emailTextField
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
alertController.addTextField { (textField) in
textField.placeholder = "Email"
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
In swift 3
let alertController = UIAlertController(title: "SecureStyle", message: "SecureStyle AlertView.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField) -> Void in
textField.secureTextEntry = true
textField.placeholder = "Password"
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (result : UIAlertAction) -> Void in
print("Cancel")
}
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { (result : UIAlertAction) -> Void in
print(alertController.textFields?.first?.text)
}
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true, completion: nil)