86

I have an IBAction that I have connected to a UITextField element in Interface Builder. (Firing on "value changed" event)

I also have a UISlider that updates the TextField element automatically when it's value gets adjusted.

When I run my app, the TextField does get updated when I adjust the slider, but the "value changed" event does not fire when this happens. The value changed event also does not fire when I edit the TextField by hand as well. (Although using the Did Editing End trigger does cause it to fire).

My question is, how can I get the value changed trigger to fire for both a programmatic update of the TextField as well as when the user adjusts the value.

Andrew Lauer Barinov
  • 5,694
  • 10
  • 59
  • 83
  • Hi, why you didn't use UITextFieldDelegate methods ? – TheRonin Nov 22 '11 at 09:07
  • 2
    They serve different purposes. `shouldChangeCharactersInRange` allows you to decide whether change should happen or not, and you need to calculate what the result would be yourself. So if the change is always going to happen, and you only care about what the changed value is, using `UIControlEventEditingChanged` is definitely easier. – superarts.org Aug 18 '17 at 15:44

8 Answers8

246

Don't use UIControlEventValueChanged for UITextField. What you want is UIControlEventEditingChanged.

Mark Adams
  • 30,776
  • 11
  • 77
  • 77
76

To get EditingChanged textfield event, I suggested add selector as

[textField addTarget:self action:@selector(textChanged:) forControlEvents:UIControlEventEditingChanged];

As textfield value changed, the changed value you will get from this textChanged: selector.

-(void)textChanged:(UITextField *)textField
{
    NSLog(@"textfield data %@ ",textField.text);
}
Kirti Nikam
  • 2,166
  • 2
  • 22
  • 43
12

IF you are assigning a delegate to the text field then note that (when you return NO from the delegate method below, the event (Editing changed) won't be triggered. Consider invoking the event listener when you do return NO from this method

(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
Nech
  • 331
  • 3
  • 11
  • 3
    The Editing Changed event will not be triggered because the field *did not change* -- that's what returning NO does! – Olie Jan 01 '15 at 16:54
  • @olie - But sometimes you change the field programmatically in that delegate method and then return NO to override the user's default text. This was my case and this answer solved the problem. – Clay Garrett Apr 24 '15 at 11:15
  • Sure, but that's not an *editing* change. If you want to do that, your code should also call the changed selector on the delegate. That way, you're in full control. – Olie Apr 24 '15 at 21:38
4

While value gets assigned programmatically, in that case, textFieldDidChange never get called because actually textField hasn't changed. For this external event needs to pass

eg., textfield.sendActions(for: .editingChanged) this will fire the editing changed event and textFieldDidChange will get called even after value changed programmatically.

Where to apply this event:

After assigning value to the text filed eg., textfield.text = "some value"

Akshay Digrase
  • 438
  • 3
  • 14
3

An old question, but the first search result I found, and none of the answers are satisfactory. I found this solution to work best: Swift UITextField subclass handle text change programmatically.

Override UITextField's text property to add a didSet(), and call your value changed function from there.

  override open var text: String? {
        didSet {
            myValueDidChange()
        }
    }
robert
  • 559
  • 4
  • 8
1

Swift 4:

class YourViewController: UIViewController {
    // MARK: Outlets
    @IBOutlet weak var titleTextField: UITextField!

    // MARK: View lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        titleTextField.delegate = self
    }
}

// MARK: UITextFieldDelegate methods
extension YourViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        print("changed")
        return true
    }
}
balazs630
  • 3,421
  • 29
  • 46
-1

As suggested by TheRonin, use UITextFieldDelegate and implement the following method

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
Ilanchezhian
  • 17,426
  • 1
  • 53
  • 55
  • Do I implement this inside of my view controller? – Andrew Lauer Barinov Nov 22 '11 at 10:02
  • Yes. Add `` in .h file interface declaration. Set the textfield's delegate to file owner through nib file. Implement the above said method inside viewcontroller. – Ilanchezhian Nov 22 '11 at 10:07
  • 1
    Does this also work when the textfield is updated programmatically? – Andrew Lauer Barinov Nov 22 '11 at 10:13
  • 3
    Wouldn't this one be more logical to use? `UITextFieldTextDidChangeNotification` , however I am not sure how to implement it. – Andrew Lauer Barinov Nov 22 '11 at 10:16
  • I am not sure how to implement this delegate method, can you include the implementation in your answer? Thanks. – Andrew Lauer Barinov Nov 22 '11 at 10:24
  • 19
    The problem with this method is that it is called _before_ the typed character is committed. That is, if you've type `fo` and then type `o`, the `textField.text` is still `fo` and not yet `foo`. You'd have to apply the change manually to get the string the textfield will be set to. – DarkDust Jul 17 '14 at 09:43
  • This is not the right method. UITextField delegate asks you to return a BOOL not to manipulate your state in some way. Mark Adams answer is the right one and the one I was searching for. – Gabriele Dec 15 '15 at 19:50
  • I second @DarkDust and Gabriele. Implement textFieldDidEndEditing instead. – Dirk Jun 23 '17 at 09:39
  • This really is not the correct answer. MarkAdams answer is correct. – Fattie Feb 03 '18 at 21:34
  • and? it is called when text is not changed yet and you should recalculate the result string if you plan to use it – Vyachaslav Gerchicov Dec 13 '18 at 12:31
-3

For Swift 3:

textField.addTarget(self, action: #selector(textChanged), for: .valueChanged)

func textChanged() { 
 .... 
}
UnRewa
  • 2,462
  • 2
  • 29
  • 31