Включить кнопку в Swift, только если все текстовые поля были заполнены
у меня возникли проблемы с выяснением, как изменить мой код, чтобы сделать это так, чтобы кнопка "готово" в навигационной панели была включена, когда мои три текстовых поля заполнены.
в настоящее время у меня есть три UITextFields и один UIButtonItem. И habitNameField, и goalField-это текстовые поля вручную, а frequencyField-это вид выбора.
@IBOutlet weak var habitNameField: UITextField!
@IBOutlet weak var goalField: UITextField!
@IBOutlet weak var frequencyField: UITextField!
@IBOutlet weak var doneBarButton: UIBarButtonItem!
у меня также есть следующая функция, которая работает, когда есть что-то набранное в первом поле.
func textField(habitNameField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let oldHabitNameText: NSString = habitNameField.text!
let newHabitNameText: NSString = oldHabitNameText.stringByReplacingCharactersInRange(range, withString: string)
doneBarButton.enabled = (newHabitNameText.length != 0)
return true
}
Я попытался изменить код так, чтобы он взял в качестве параметров два других поля и включил doneBarButton только в том случае, если все три поля были заполнены.
func textField(habitNameField: UITextField, goalField: UITextField, frequencyField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let habitNameText: NSString = (habitNameField.text!).stringByReplacingCharactersInRange(range, withString: string)
let goalText: NSString = (goalField.text!).stringByReplacingCharactersInRange(range, withString: string)
let frequencyText: NSString = (frequencyField.text!).stringByReplacingCharactersInRange(range, withString: string)
doneBarButton.enabled = (habitNameText.length != 0) && (goalText.length != 0) && (frequencyText.length != 0)
return true
}
однако это не работает, даже когда я заполняю все три текстовых поля.
Я был бы очень признателен за любую помощь, и спасибо всем, кто вносит свой вклад в продвижение!
все вот код:
class HabitDetailViewController: UITableViewController, UITextFieldDelegate, UIPickerViewDataSource,UIPickerViewDelegate {
@IBOutlet weak var habitNameField: UITextField!
@IBOutlet weak var goalField: UITextField!
@IBOutlet weak var doneBarButton: UIBarButtonItem!
@IBOutlet weak var frequencyField: UITextField!
var frequencies = ["Day", "Week", "Month", "Year"]
var frequencyPicker = UIPickerView()
var habitToEdit: HabitItem?
weak var delegate: HabitDetailViewControllerDelegate?
@IBAction func cancel() {
delegate?.habitDetailViewControllerDidCancel(self)
}
@IBAction func done() {
print("You plan to do (habitNameField.text!) (goalField.text!) times a (frequencyField.text!.lowercaseString).")
if let habit = habitToEdit {
habit.name = habitNameField.text!
habit.numberLeft = Int(goalField.text!)!
habit.frequency = frequencyField.text!
delegate?.habitDetailViewController(self, didFinishEditingHabit: habit)
} else {
let habit = HabitItem()
habit.name = habitNameField.text!
habit.numberLeft = Int(goalField.text!)!
habit.frequency = frequencyField.text!
habit.completed = false
delegate?.habitDetailViewController(self, didFinishAddingHabit: habit)
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
habitNameField.becomeFirstResponder()
frequencyPicker.hidden = false
}
override func viewDidLoad() {
super.viewDidLoad()
frequencyPicker.dataSource = self
frequencyPicker.delegate = self
doneBarButton.enabled = false
habitNameField.addTarget(self, action: "checkFields:", forControlEvents: .EditingChanged)
goalField.addTarget(self, action: "checkFields:", forControlEvents: .EditingChanged)
frequencyField.addTarget(self, action: "checkFields:", forControlEvents: .EditingChanged)
frequencyField.inputView = frequencyPicker
if let habit = habitToEdit {
title = "Edit Item"
habitNameField.text = habit.name
goalField.text = String(habit.numberLeft)
doneBarButton.enabled = true
}
}
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
return nil
}
func textField(habitNameField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let oldHabitNameText: NSString = habitNameField.text!
let newHabitNameText: NSString = oldHabitNameText.stringByReplacingCharactersInRange(range, withString: string)
doneBarButton.enabled = (newHabitNameText.length != 0)
return true
}
func checkFields(sender: UITextField) {
sender.text = sender.text?.stringByTrimmingCharactersInSet(.whitespaceCharacterSet())
guard
let habit = habitNameField.text where !habit.isEmpty,
let goal = goalField.text where !goal.isEmpty,
let frequency = frequencyField.text where !frequency.isEmpty
else { return }
// enable your button if all conditions are met
doneBarButton.enabled = true
}
8 ответов
Xcode 9 * Swift 4
вы можете addTarget
к текстовым полям для мониторинга события управления .editingChanged
и использовать один метод селектор для всех из них:
override func viewDidLoad() {
super.viewDidLoad()
doneBarButton.isEnabled = false
[habitNameField, goalField, frequencyField].forEach({ .addTarget(self, action: #selector(editingChanged), for: .editingChanged) })
}
создайте метод селектора и используйте guard
в сочетании с where
предложение (Swift 3/4 использует запятую), чтобы убедиться, что все текстовые поля не пусты, иначе просто верните. Swift 3 не требует @objc, но Swift 4 делает:
@objc func editingChanged(_ textField: UITextField) {
if textField.text?.characters.count == 1 {
if textField.text?.characters.first == " " {
textField.text = ""
return
}
}
guard
let habit = habitNameField.text, !habit.isEmpty,
let goal = goalField.text, !goal.isEmpty,
let frequency = frequencyField.text, !frequency.isEmpty
else {
doneBarButton.isEnabled = false
return
}
doneBarButton.isEnabled = true
}
Swift 3 / Xcode 8.2
override func viewDidLoad() {
super.viewDidLoad()
setupAddTargetIsNotEmptyTextFields()
}
func setupAddTargetIsNotEmptyTextFields() {
okButton.isHidden = true //hidden okButton
nameUserTextField.addTarget(self, action: #selector(textFieldsIsNotEmpty),
for: .editingChanged)
emailUserTextField.addTarget(self, action: #selector(textFieldsIsNotEmpty),
for: .editingChanged)
passwordUserTextField.addTarget(self, action: #selector(textFieldsIsNotEmpty),
for: .editingChanged)
confimPasswordUserTextField.addTarget(self, action: #selector(textFieldsIsNotEmpty),
for: .editingChanged)
}
а затем создайте способ селектора и использовать гвардии:
@objc func textFieldsIsNotEmpty(sender: UITextField) {
sender.text = sender.text?.trimmingCharacters(in: .whitespaces)
guard
let name = nameUserTextField.text, !name.isEmpty,
let email = emailUserTextField.text, !email.isEmpty,
let password = passwordUserTextField.text, !password.isEmpty,
let confirmPassword = confimPasswordUserTextField.text,
password == confirmPassword
else
{
self.okButton.isHidden = true
return
}
// enable okButton if all conditions are met
okButton.isHidden = false
}
P. S. В Свифт 3 "здесь" ==>>> ","
лучшим способом было бы добавить наблюдателя в метод ViewDidLoad. Чем просто проверить метод делегата textField, заполнены ли все текстовые поля или нет. После того, как его заполненный вызов oberserver метод & в том, что вам просто нужно включить кнопку.
Примечание:
- вы можете использовать observer для включения или выключения кнопки
надеюсь, это поможет вам.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if (textField == self.textField1) { /* do Something */ }
else if (textField == self.textField2) { /* do Something */ }
else if (textField == self.textField3) { /* do Something */ }
// regardless of what you do before, doneBarButton is enabled when all are not empty
doneBarButton.enabled = (textField1.length != 0) && (textField2.length != 0) && (textField3.length != 0)
return true
}
почему бы не переместить функцию проверки в отдельную функцию
func setDoneButtonStatus()
{
let habitNameText: NSString = (habitNameField.text!).stringByReplacingCharactersInRange(range, withString: string)
let goalText: NSString = (goalField.text!).stringByReplacingCharactersInRange(range, withString: string)
let frequencyText: NSString = (frequencyField.text!).stringByReplacingCharactersInRange(range, withString: string)
doneBarButton.enabled = (habitNameText.length != 0) && (goalText.length != 0) && (frequencyText.length != 0)
}
и затем использовать
func textFieldShouldReturn(textField: UITextField) -> Bool
{
textField.resignFirstResponder()
setDoneButtonStatus()
}
это работает для меня: Надеюсь, это поможет
func textFieldDidEndEditing(textField: UITextField) {
if txtField1.hasText() && textField2.hasText() && textField3.hasText(){
doneBarButton.enabled = true
}
}
Я пошел вперед и отведенную немного в вспомогательный класс, который можно использовать для быстрого проекта.
import Foundation
import UIKit
class ButtonValidationHelper {
var textFields: [UITextField]!
var buttons: [UIButton]!
init(textFields: [UITextField], buttons: [UIButton]) {
self.textFields = textFields
self.buttons = buttons
attachTargetsToTextFields()
disableButtons()
checkForEmptyFields()
}
//Attach editing changed listeners to all textfields passed in
private func attachTargetsToTextFields() {
for textfield in textFields{
textfield.addTarget(self, action: #selector(textFieldsIsNotEmpty), for: .editingChanged)
}
}
@objc private func textFieldsIsNotEmpty(sender: UITextField) {
sender.text = sender.text?.trimmingCharacters(in: .whitespaces)
checkForEmptyFields()
}
//Returns true if the field is empty, false if it not
private func checkForEmptyFields() {
for textField in textFields{
guard let textFieldVar = textField.text, !textFieldVar.isEmpty else {
disableButtons()
return
}
}
enableButtons()
}
private func enableButtons() {
for button in buttons{
button.isEnabled = true
}
}
private func disableButtons() {
for button in buttons{
button.isEnabled = false
}
}
}
а затем в вашем представлении контроллер просто просто init помощник с
buttonHelper = ButtonValidationHelper(textFields: [textfield1, textfield2, textfield3, textfield4], buttons: [button])
убедитесь, что вы держите сильную ссылку сверху, чтобы предотвратить освобождение
var buttonHelper: ButtonValidationHelper!
вы можете создать массив текстовых полей [UITextField]
или коллекция розеток. Назовем массив textFields
или что-то подобное.
doneBarButton.isEnabled = !textFields.flatMap { .text?.isEmpty }.contains(true)
и вызовите код выше в методе, который отслеживает изменения текста текстового поля.