Włącz Przycisk w języku Swift tylko wtedy, gdy wszystkie pola tekstowe zostały wypełnione
Mam problem z wymyśleniem, jak zmienić mój kod, aby tak zrobił przycisk Gotowe na pasku nawigacyjnym jest włączony, gdy moje trzy pola tekstowe są wypełnione.
Obecnie mam trzy UITextFields i jeden UIButtonItem. Zarówno habitNameField, jak i goalField są polami tekstu ręcznego, a frequencyField jest widokiem pickera.
@IBOutlet weak var habitNameField: UITextField!
@IBOutlet weak var goalField: UITextField!
@IBOutlet weak var frequencyField: UITextField!
@IBOutlet weak var doneBarButton: UIBarButtonItem!
Mam również następującą funkcję, która działa, gdy coś jest wpisane w pierwszym polu.
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
}
Próbowałem zmienić kod tak, że wziął w pozostałych dwóch polach jako parametry i włączył doneBarButton tylko wtedy, gdy wszystkie trzy pola zostały wypełnione.
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
}
Jednak nie działa, nawet gdy wypełniam wszystkie trzy pola tekstowe.
Byłbym naprawdę wdzięczny za każdą pomoc i dziękuję każdemu, kto wniesie swój wkład z góry!
Cały kod tutaj:
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 answers
Xcode 9 * Swift 4
Możesz addTarget
do swoich pól tekstowych monitorować Zdarzenie control .editingChanged
i użyć jednej metody selektora dla wszystkich z nich:
override func viewDidLoad() {
super.viewDidLoad()
doneBarButton.isEnabled = false
[habitNameField, goalField, frequencyField].forEach({ $0.addTarget(self, action: #selector(editingChanged), for: .editingChanged) })
}
Utwórz metodę selektora i użyj guard
w połączeniu z klauzulą where
(Swift 3/4 używa przecinka), aby upewnić się, że wszystkie pola tekstowe nie są puste, w przeciwnym razie po prostu zwróć. Swift 3 nie wymaga @objc, ale Swift 4 tak:
@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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 19:13:07
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)
}
A następnie utwórz metodę selektora i użyj guard :
@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. w swift 3 " Gdzie" ==>>> ","
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-15 22:51:24
Najlepszym sposobem byłoby dodanie obserwatora w metodzie ViewDidLoad. Niż tylko sprawdzić w textField Delegate metody, czy wszystkie pola tekstowe są wypełnione, czy nie. Po wypełnieniu wywołania metoda oberserver i w tym wystarczy włączyć przycisk.
Uwaga:
- możesz użyć observer zarówno do włączania, jak i wyłączania przycisku
Mam nadzieję, że ci pomoże.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-22 07:34:26
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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-22 07:24:59
Dlaczego nie przenieść funkcji sprawdzania do osobnej funkcji
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)
}
A następnie użyj
func textFieldShouldReturn(textField: UITextField) -> Bool
{
textField.resignFirstResponder()
setDoneButtonStatus()
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-22 07:28:50
To działa dla mnie: Hope it helps
func textFieldDidEndEditing(textField: UITextField) {
if txtField1.hasText() && textField2.hasText() && textField3.hasText(){
doneBarButton.enabled = true
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-14 04:03:13
Poszedłem dalej i wyodrębniłem to trochę do klasy pomocniczej, którą można wykorzystać do ich szybkiego projektu.
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
}
}
}
A następnie w kontrolerze widoku po prostu init helpera za pomocą
buttonHelper = ButtonValidationHelper(textFields: [textfield1, textfield2, textfield3, textfield4], buttons: [button])
Upewnij się, że trzymasz silne odniesienie na górze, aby zapobiec dealokacji
var buttonHelper: ButtonValidationHelper!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-21 18:54:34
Możesz utworzyć tablicę pól tekstowych [UITextField]
lub kolekcję wyjściową. Nazwijmy tablicę textFields
lub coś w tym stylu.
doneBarButton.isEnabled = !textFields.flatMap { $0.text?.isEmpty }.contains(true)
I wywołanie powyższego kodu w metodzie monitorującej zmiany tekstu w polu tekstowym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-11 00:43:34