2016-01-22 50 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) 

並在監視文本字段文本更改的方法中調用上面的代碼。

相關問題