34

I cant figure out which UITextField is currently active so i can clear its text if they hit cancel on a UIBarButtonItem. Here is my code. There is a view with a UIPickerView,UIToolBar and two bar button items. The cancel item has an action that will clear its text only i cant figure out how to get the correct UITextField.

I've tried these both:

@IBAction func cancelText(sender: AnyObject) {


    if self.truckYear.editing == true{

        println("truckYear")

        clearText(self.truckYear)
    } else if self.truckMake.editing == true{

        clearText(self.truckMake)
    }
}
@IBAction func doneText(sender: AnyObject) {

    pickerView.hidden = true
}


func clearText(textField:UITextField){

    println("in clear text")

    textField.text = nil
}

And:

@IBAction func cancelText(sender: AnyObject) {


    if self.truckYear.isFirstResponder(){

        println("truckYear")

        clearText(self.truckYear)
    } else if self.truckMake.isFirstResponder(){

        clearText(self.truckMake)
    }
}
@IBAction func doneText(sender: AnyObject) {

    pickerView.hidden = true
}


func clearText(textField:UITextField){

    println("in clear text")

    textField.text = nil
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Shawjak3
  • 541
  • 1
  • 5
  • 18

7 Answers7

53

You can declare a UITextField property in your class, and assign the current text field to it in textFieldDidBeginEditing. Then you can just call this text field whenever you need to.

class ViewController : UIViewController, UITextFieldDelegate {

   var activeTextField = UITextField()

   // Assign the newly active text field to your activeTextField variable
   func textFieldDidBeginEditing(textField: UITextField) {

        self.activeTextField = textField
   }

   // Call activeTextField whenever you need to
   func anotherMethod() {

       // self.activeTextField.text is an optional, we safely unwrap it here
       if let activeTextFieldText = self.activeTextField.text {
             print("Active text field's text: \(activeTextFieldText)")
             return;
       }

       print("Active text field is empty")
   }
}
Randy
  • 4,335
  • 3
  • 30
  • 64
  • So could I use that and then in the UIBarButtonItem Action just say clearText(self.activeTextField) ? – Shawjak3 Jun 18 '15 at 15:05
  • Yes, you would be able to do that. – Randy Jun 18 '15 at 15:08
  • Ok I just tried it and no errors but the text isn't being set to nill. This is my code, ` func textFieldDidBeginEditing(textField: UITextField) { self.activeTextfield = textField } @IBAction func cancelText(sender: AnyObject) { println("action fired") self.activeTextfield.text = nil self.pickerView.hidden = true } @IBAction func doneText(sender: AnyObject) { pickerView.hidden = true }` – Shawjak3 Jun 18 '15 at 15:19
  • In your `cancelText(...)` method, could you add `NSLog("text in activeTextField : %@", self.activeTextField.text)` before trying to clear it ? It should show you the content of this text field. Also, try to clear your text like that : self.activeTextfield.text = "" – Randy Jun 18 '15 at 15:26
  • Ya I will add it, I put a println statement in the textFieldDidBeginEditing and its not making it into that method. Also how did you post code in the comment, I used the backticks but nothing happened. If I set the text to nil it will put the placeholder text back in, will it still do that if I set it to ""? – Shawjak3 Jun 18 '15 at 15:29
  • Here's the output `2015-06-18 09:31:15.940 LTmobile[18867:4494135] text in activeTextField : ` – Shawjak3 Jun 18 '15 at 15:32
  • Did you set the delegate property of your textfield to "self" ( `myTextField.delegate = self` ? Did you assign the delegate object `UITextField` to your viewcontroller ? ( As you can see in the first line of my answer ( `, UITextFieldDelegate` ). I use "`" to set my code. – Randy Jun 18 '15 at 15:34
  • And normally, setting your textfield.text to nil should work, I definitely think that you should read some documentations about delegation as Almo said. – Randy Jun 18 '15 at 15:35
  • Yes the activeTextfield is delegate, all my textfields are delegate on the scene and I have the UITextFieldDelegate protocol in the view controller. Its just weird that the delegate method didBeginEditing isnt firing because I have the touchesBegan delegate method working just fine. – Shawjak3 Jun 18 '15 at 15:39
  • Can you post the whole code for your view controller ? – Randy Jun 18 '15 at 15:42
  • 1
    I figured it out, thanks for all your help. So come to find out I was already using didBeginEditing further down, (I know Im a noob), and then your code worked brilliantly. Thank you! – Shawjak3 Jun 18 '15 at 16:57
  • Can I do this in Cocoa by just replacing the UI with NS? – Jack Feb 08 '17 at 04:58
  • I guess so yes, why don't you try and tell us? – Randy Feb 08 '17 at 08:25
24

In swift 4:

you can get the active UITextField like that

extension UIView {
func getSelectedTextField() -> UITextField? {

    let totalTextFields = getTextFieldsInView(view: self)

    for textField in totalTextFields{
        if textField.isFirstResponder{
            return textField
        }
    }

    return nil

}

func getTextFieldsInView(view: UIView) -> [UITextField] {

    var totalTextFields = [UITextField]()

    for subview in view.subviews as [UIView] {
        if let textField = subview as? UITextField {
            totalTextFields += [textField]
        } else {
            totalTextFields += getTextFieldsInView(view: subview)
        }
    }

    return totalTextFields
}}

and then you call it like that

let current = view.getSelectedTextField()
Reimond Hill
  • 4,278
  • 40
  • 52
14

In order to improve @Reimond's answer Swift 4

extension UIView {
    var textFieldsInView: [UITextField] {
        return subviews
            .filter ({ !($0 is UITextField) })
            .reduce (( subviews.compactMap { $0 as? UITextField }), { summ, current in
                return summ + current.textFieldsInView
        })
    }
    var selectedTextField: UITextField? {
        return textFieldsInView.filter { $0.isFirstResponder }.first
    }
}

usage:

view.selectedTextField

Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
1

you can assign a tag to all your text feild and in textFieldDidBeginEditing check your current textFeild.tag and it's clear witch textfeild is in use .

0

Use the delegate:

optional func textFieldDidEndEditing(_ textField: UITextField)

This will tell you when the active textfield finishes editing, and textField will contain a pointer to the one that's no longer going to be active.

Almo
  • 15,538
  • 13
  • 67
  • 95
  • Can you give me an example of how to implement that into that action? – Shawjak3 Jun 18 '15 at 15:09
  • 1
    I really recommend learning how to implement delegate methods. You'll have no end of trouble with the Cocoa API if you don't have that figured out. – Almo Jun 18 '15 at 15:15
  • I implement some delegate methods but Im fairly new to swift so I dont have all the pieces to the puzzle but i'll take a shot at it. – Shawjak3 Jun 18 '15 at 15:22
0
/// Finds the textField that is the first responder in a view hierarchy
func findActiveTextField(in subviews: [UIView], textField: inout UITextField?) {

    guard textField == nil else { return }

    for view in subviews {
        if let tf = view as? UITextField, view.isFirstResponder {
            textField = tf
            break
        }
        else if !view.subviews.isEmpty {
            findActiveTextField(in: view.subviews, textField: &textField)
        }
    }
}

// Usage
var aView: UIView = UIView()
var activeField : UITextField?
findActiveTextField(in: aView.subviews, textField: &activeField)
John Slade
  • 219
  • 1
  • 8
0

I wrote a library to handle basic Form Creation Swift Pop Form. It doesn't use tags but rather sets a datasource that contains fields and uses indexPathForCell to query which is the active textfield. Check out the source code for more!

aBikis
  • 323
  • 4
  • 16