如何根据 UITextField 禁用 UIAlertAction?
How to disable UIAlertAction depending on UITextField?
我有一个 action
,它会在点击按钮时创建一个 alert
。
这个alert
由两个textfields
和两个actions
组成(add
和dismiss
)。
如果 textfields
为空,我有什么简单的方法可以禁用 add
按钮(稍后我会检查第二个是否真的是 URL 但让我们让事情集中在action
这里)?
这是我的代码和我到目前为止尝试过的代码:
@IBAction func addSourceTapped(_ sender: Any) {
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
}
alert.addTextField { (textField) in
textField.placeholder = "Link"
}
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true
}
let action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true //doesn't do anything yet..
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
}
self.tableView.reloadData()
}
let action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
您不能在任何地方编写 UITextField 验证代码(启用/禁用操作的代码)!!每次 UItextfield 更新时都必须完成此验证。因此,为此您需要从 UITextField 获取委托以进行更新
您需要全局保存文本字段并将文本字段委托分配给您的ViewController。通过这样做,您可以编写代码来验证 UI 中文本字段的代码ViewController 并以编程方式启用或禁用您的操作
class YOUR_CLASS_NAME:UIViewController,UITextFieldDelegate {
var alert: UIAlertController!
var action: UIAlertAction!
var action2: UIAlertAction!
var nameTextFeld:UITextField!
var linkTextFeld:UITextField!
@IBAction func addSourceTapped(_ sender: Any) {
alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
self.nameTextFeld = textField
self.nameTextFeld.placeholder = "Name"
self.nameTextFeld.delegate = self
}
alert.addTextField { (textField) in
self.linkTextFeld = textField
self.linkTextFeld.placeholder = "Link"
self.linkTextFeld.delegate = self
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = self.alert.textFields!.first!.text!
let link = self.alert.textFields!.last!.text!
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
self.tableView.reloadData()
}
action.isEnabled = false
action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if !((nameTextFeld.text?.isEmpty)! && (linkTextFeld.text?.isEmpty)!) {
action.isEnabled = true
}
return true
}
}
通过在添加时配置文本字段来做到这一点
alert.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = "Name"
// Other configuration such as textField.autocapitalizationType = .words
NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in
let nameField = alert.textFields![0] as UITextField
let linkField = alert.textFields![1] as UITextField
action.isEnabled = self.getTextFieldContent(nameField) != "" && self.getTextFieldContent(linkField) != ""
}
})
您需要分别为两个文本字段执行此操作(尽管您可以通过重复使用相同的代码来执行此操作)。另请注意,如果您直接在操作的处理程序块中引用文本字段,它将创建一个强引用循环并且您的控制器将不会被取消。为避免这种情况,请使用像这样的本地可空变量引用文本字段
var tf: UITextField?
let action = UIAlertAction(title: "Add", style: .default) { (_) in
guard let textField = tf else {
return;
}
let name = textField.text!
// Rest the action here
}
alertController.addTextField { (textField) in
// Configure textField here
tf = textField
}
你最好使用动作,它比其他答案更简单。如果您尝试使用委托,方法 didBeginEditing 和 didEndEditing 将无法正确处理它。 shouldChangeCharactersIn range 也不行,它在文本字段中出现输入之前执行,因此在那里检查文本字段的文本 属性 是不正确的。
private var action: UIAlertAction!
@IBAction func addSourceTapped(_ sender: Any) {
////////
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged) // <---
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
/////
}
action.isEnabled = false
alert.addAction(action)
////////
}
@objc private func textFieldDidChange(_ field: UITextField) {
action.isEnabled = field.text?.count ?? 0 > 0
}
使用动作的程序化解决方案。
将按钮添加到 class 并根据文本字段中所做的更改继续更改其状态。
import UIKit
final class ViewWithConfirmationController: UIViewController {
private let askButton = UIButton()
private let deleteAction = UIAlertAction(
title: "Confirm",
style: .default
) { _ in
// Confirmed
}
init() {
super.init(nibName: nil, bundle: nil)
view.addSubview(askButton)
askButton.setTitle("Call alert", for: .normal)
askButton.addTarget(
self,
action: #selector(callAlert),
for: .touchUpInside
)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func callAlert() {
let alert = UIAlertController(
title: "Confirmation alert",
message: """
Do you really want to do that?
Please type in the magic word to confirm.
""",
preferredStyle: .alert
)
alert.addTextField { textField in
textField.placeholder = "Magic word"
textField.addTarget(
self,
action: #selector(self.textFieldDidChange(_:)),
for: .editingChanged
)
}
alert.addAction(
UIAlertAction(
title: "Cancel",
style: .cancel,
handler: { _ in }
))
alert.addAction(deleteAction)
// Confirm button will disabled until user type current organisation name
deleteAction.isEnabled = false
present(alert, animated: true, completion: nil)
}
@objc private func textFieldDidChange(_ field: UITextField) {
guard let text = field.text else {
print("Can't get text from text field in \(#function)")
return
}
deleteAction.isEnabled = !text.isEmpty
}
}
我有一个 action
,它会在点击按钮时创建一个 alert
。
这个alert
由两个textfields
和两个actions
组成(add
和dismiss
)。
如果 textfields
为空,我有什么简单的方法可以禁用 add
按钮(稍后我会检查第二个是否真的是 URL 但让我们让事情集中在action
这里)?
这是我的代码和我到目前为止尝试过的代码:
@IBAction func addSourceTapped(_ sender: Any) {
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
}
alert.addTextField { (textField) in
textField.placeholder = "Link"
}
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true
}
let action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true //doesn't do anything yet..
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
}
self.tableView.reloadData()
}
let action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
您不能在任何地方编写 UITextField 验证代码(启用/禁用操作的代码)!!每次 UItextfield 更新时都必须完成此验证。因此,为此您需要从 UITextField 获取委托以进行更新
您需要全局保存文本字段并将文本字段委托分配给您的ViewController。通过这样做,您可以编写代码来验证 UI 中文本字段的代码ViewController 并以编程方式启用或禁用您的操作
class YOUR_CLASS_NAME:UIViewController,UITextFieldDelegate {
var alert: UIAlertController!
var action: UIAlertAction!
var action2: UIAlertAction!
var nameTextFeld:UITextField!
var linkTextFeld:UITextField!
@IBAction func addSourceTapped(_ sender: Any) {
alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
self.nameTextFeld = textField
self.nameTextFeld.placeholder = "Name"
self.nameTextFeld.delegate = self
}
alert.addTextField { (textField) in
self.linkTextFeld = textField
self.linkTextFeld.placeholder = "Link"
self.linkTextFeld.delegate = self
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = self.alert.textFields!.first!.text!
let link = self.alert.textFields!.last!.text!
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
self.tableView.reloadData()
}
action.isEnabled = false
action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if !((nameTextFeld.text?.isEmpty)! && (linkTextFeld.text?.isEmpty)!) {
action.isEnabled = true
}
return true
}
}
通过在添加时配置文本字段来做到这一点
alert.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = "Name"
// Other configuration such as textField.autocapitalizationType = .words
NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in
let nameField = alert.textFields![0] as UITextField
let linkField = alert.textFields![1] as UITextField
action.isEnabled = self.getTextFieldContent(nameField) != "" && self.getTextFieldContent(linkField) != ""
}
})
您需要分别为两个文本字段执行此操作(尽管您可以通过重复使用相同的代码来执行此操作)。另请注意,如果您直接在操作的处理程序块中引用文本字段,它将创建一个强引用循环并且您的控制器将不会被取消。为避免这种情况,请使用像这样的本地可空变量引用文本字段
var tf: UITextField?
let action = UIAlertAction(title: "Add", style: .default) { (_) in
guard let textField = tf else {
return;
}
let name = textField.text!
// Rest the action here
}
alertController.addTextField { (textField) in
// Configure textField here
tf = textField
}
你最好使用动作,它比其他答案更简单。如果您尝试使用委托,方法 didBeginEditing 和 didEndEditing 将无法正确处理它。 shouldChangeCharactersIn range 也不行,它在文本字段中出现输入之前执行,因此在那里检查文本字段的文本 属性 是不正确的。
private var action: UIAlertAction!
@IBAction func addSourceTapped(_ sender: Any) {
////////
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged) // <---
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
/////
}
action.isEnabled = false
alert.addAction(action)
////////
}
@objc private func textFieldDidChange(_ field: UITextField) {
action.isEnabled = field.text?.count ?? 0 > 0
}
使用动作的程序化解决方案。 将按钮添加到 class 并根据文本字段中所做的更改继续更改其状态。
import UIKit
final class ViewWithConfirmationController: UIViewController {
private let askButton = UIButton()
private let deleteAction = UIAlertAction(
title: "Confirm",
style: .default
) { _ in
// Confirmed
}
init() {
super.init(nibName: nil, bundle: nil)
view.addSubview(askButton)
askButton.setTitle("Call alert", for: .normal)
askButton.addTarget(
self,
action: #selector(callAlert),
for: .touchUpInside
)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func callAlert() {
let alert = UIAlertController(
title: "Confirmation alert",
message: """
Do you really want to do that?
Please type in the magic word to confirm.
""",
preferredStyle: .alert
)
alert.addTextField { textField in
textField.placeholder = "Magic word"
textField.addTarget(
self,
action: #selector(self.textFieldDidChange(_:)),
for: .editingChanged
)
}
alert.addAction(
UIAlertAction(
title: "Cancel",
style: .cancel,
handler: { _ in }
))
alert.addAction(deleteAction)
// Confirm button will disabled until user type current organisation name
deleteAction.isEnabled = false
present(alert, animated: true, completion: nil)
}
@objc private func textFieldDidChange(_ field: UITextField) {
guard let text = field.text else {
print("Can't get text from text field in \(#function)")
return
}
deleteAction.isEnabled = !text.isEmpty
}
}