2016-01-22 47 views
8

我无法确定如何更改我的代码,以便在填写我的三个文本字段时启用导航栏中的完成按钮。只有在所有文本字段已被填写的情况下才能在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 
} 

回答

18

Xcode 8.3.2•Swift 3。1

您可以addTarget应用于文本字段来监测控制事件.editingChanged,并使用一个单一的选择方法为所有这些:

override func viewDidLoad() { 
    super.viewDidLoad() 
    doneBarButton.isEnabled = false 
    habitNameField.addTarget(self, action: #selector(editingChanged), for: .editingChanged) 
    goalField.addTarget(self, action: #selector(editingChanged), for: .editingChanged) 
    frequencyField.addTarget(self, action: #selector(editingChanged), for: .editingChanged) 
} 

创建的选择方法和使用guardwhere子句结合(斯威夫特3使用逗号),以确保所有的文本字段不为空,否则只是返回:

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 
} 

sample

+0

这是行得通的,但由于某些原因,即使只填写了字段,它也能正常工作。为什么? –

+0

Durr。这是我的一个新秀错误。感谢您帮助我理解这一点。此外,频率的最终文本字段不起作用,因为它是一个选取器视图。有关于此的任何想法? –

+0

您可以创建一个布尔变量来监视它,并在用户设置它时将其标记。然后,只需将它添加到警卫声明 –

1
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 

}

1

为何不动检查功能到一个单独的功能

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() 
} 
2

最好的方法是在ViewDidLoad方法中添加观察者。不仅仅是检查textField委托方法是否所有的TextFields都被填满了。一旦它填补了电话oberserver方法&在那你只需要启用按钮。

注:

  • 可以使用观察员都启用或禁用按钮

希望它会帮助你。

1

这个工作对我来说:希望它可以帮助

func textFieldDidEndEditing(textField: UITextField) { 
     if txtField1.hasText() && textField2.hasText() && textField3.hasText(){ 
      doneBarButton.enabled = true 
     } 
    } 
+0

请注意,这仅适用于iOS(10.0及更高版本),tvOS(10.0及更高版本)。顺便说一句,它不是一种方法了。现在它是一个计算属性 –

6

斯威夫特3 /的Xcode 8.2

enter image description here

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.在SWIFT 3“其中” == >>>“

+0

应该是正确的答案,它对我来说工作正常,委托方法不提供像.editingChanged – Bradley

+0

伟大的解决方案!您需要将'textFieldsIsNotEmpty'标记为'@objc',否则编译器将引发错误。请更新答案。 – Prabhav

+0

嘿,@Prabhav。 准备好了,谢谢 –

1

我说干就干,有点抽象了这一点,进入一个可以使用他们迅速的项目一个辅助类。

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 
    } 
    } 

} 

,然后在视图控制器只是简单的初始化与

buttonHelper = ButtonValidationHelper(textFields: [textfield1, textfield2, textfield3, textfield4], buttons: [button]) 

助手确保你在顶部保持很强的参考,以防止释放

var buttonHelper: ButtonValidationHelper! 
0

您可以创建一个数组文本字段[UITextField]或出口集合。我们来调用数组textFields或类似的东西。

doneBarButton.isEnabled = !textFields.flatMap { $0.text?.isEmpty }.contains(true) 

并在监视文本字段文本更改的方法中调用上面的代码。

相关问题