コードを変更して、3つのテキストフィールドに入力したときにナビゲーションバーの[完了]ボタンが有効になるようにコードを変更する方法がわかりません。
現在、3つのUITextFieldと1つの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
}
コードを変更して、他の2つのフィールドをパラメーターとして受け取り、3つのフィールドがすべて入力された場合にのみ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
}
ただし、3つのテキストフィールドすべてに入力しても動作しません。
私はどんな助けも本当に感謝します、そして事前に貢献してくれた人に感謝します!
すべてのコードはこちら:
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
}
Xcode 9•Swift 4
テキストフィールドにaddTarget
して、制御イベントを監視できます.editingChanged
そして、それらすべてに対して単一のセレクターメソッドを使用します。
override func viewDidLoad() {
super.viewDidLoad()
doneBarButton.isEnabled = false
[habitNameField, goalField, frequencyField].forEach({ $0.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)
}
次にselectorメソッドを作成し、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
}
追伸In Swift 3 "where" == >>> "、」
最善の方法は、ViewDidLoadメソッドにオブザーバーを追加することです。すべてのTextFieldがいっぱいになっているかどうかをtextField Delegateメソッドでチェックインするだけではありません。いっぱいになったらoberserverメソッドを呼び出して、ボタンを有効にするだけです。
注:
それがあなたを助けることを願っています。
私は先に進み、これをビットSwiftプロジェクトに使用できるヘルパークラスに少し抽象化しました。
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
}
}
}
そして、View Controllerでヘルパーを単にinitするだけです
buttonHelper = ButtonValidationHelper(textFields: [textfield1, textfield2, textfield3, textfield4], buttons: [button])
割り当て解除を防ぐために、必ず最上位に強力な参照を保持してください
var buttonHelper: ButtonValidationHelper!
チェック機能を別の機能に移行しないのはなぜですか
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
}
}
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
}
テキストフィールドの配列を作成できます[UITextField]
またはアウトレットコレクション。配列textFields
またはそのようなものを呼び出しましょう。
doneBarButton.isEnabled = !textFields.flatMap { $0.text?.isEmpty }.contains(true)
また、テキストフィールドのテキストの変更を監視するメソッドで上記のコードを呼び出します。
Xcode 10.2•Swift 4.3上記のLeo Dabusのバージョン。
このソリューションは、ユーザーを追加するためのもので、おそらくこのような検証の最も一般的な実装です。
override func viewDidLoad() {
super.viewDidLoad()
addUserButton.backgroundColor = disabledButtonColor
addUserButton.isEnabled = false
[emailField, userNameField, firstNameField, lastNameField].forEach { (field) in
field?.addTarget(self,
action: #selector(editingChanged(_:)),
for: .editingChanged)
}}
@objc private func editingChanged(_ textField: UITextField) {
if textField.text?.count == 1 {
if textField.text?.first == " " {
textField.text = ""
return
}
}
guard
let email = emailField.text, !email.isEmpty,
let userName = userNameField.text, !userName.isEmpty,
let firstName = firstNameField.text, !firstName.isEmpty,
let lastName = lastNameField.text, !lastName.isEmpty
else {
addUserButton.isEnabled = false
addUserButton.backgroundColor = disabledButtonColor
return
}
addUserButton.isEnabled = true
addUserButton.backgroundColor = activeButtonColor
}