12

How should I go about detecting if typing has stopped in a UITextField? Should I use the UITextFieldTextDidEndEditingNotification function of some sorts? I a trying to create a instagram like search where it will display the results after a second of not typing.

Max
  • 318
  • 1
  • 3
  • 11
  • What is it exactly you want to detect? When the user leaves the text field or when the user isn't typing anymore but the focus is still on the text field? – rmaddy Jul 05 '15 at 04:53
  • Possible duplicate of [How to detect a pause in input for UISearchBar/UITextField?](http://stackoverflow.com/questions/7061377/how-to-detect-a-pause-in-input-for-uisearchbar-uitextfield) – Cristik Sep 07 '16 at 03:07

4 Answers4

22

This is how I did and it works for me in Swift 3

import UIKit

// don't forget to add UITextFieldDelegate
class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!

    var searchTimer: Timer?

    override func viewDidLoad() {
        super.viewDidLoad()

        // declare textField as delegate
        self.textField.delegate = self

        // handle the editingChanged event by calling (textFieldDidEditingChanged(-:))
        self.textField.addTarget(self, action: #selector(textFieldDidEditingChanged(_:)), for: .editingChanged)
    }

    // reset the searchTimer whenever the textField is editingChanged
    func textFieldDidEditingChanged(_ textField: UITextField) {

        // if a timer is already active, prevent it from firing
        if searchTimer != nil {
            searchTimer?.invalidate()
            searchTimer = nil
        }

        // reschedule the search: in 1.0 second, call the searchForKeyword method on the new textfield content
        searchTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(searchForKeyword(_:)), userInfo: textField.text!, repeats: false)
    }

    func searchForKeyword(_ timer: Timer) {

        // retrieve the keyword from user info
        let keyword = timer.userInfo!

        print("Searching for keyword \(keyword)")
    }

}
ThetNaing Mizo
  • 4,049
  • 2
  • 14
  • 15
18

This approach uses an NSTimer to schedule a search 1 second after the text field changes. If a new character is typed before that second is up, the timer starts over. This way, the search is only triggered starts after the last change.

First things first, make sure the ViewController is conforms to the UITextFieldDelegate protocol:

//
//  ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UITextFieldDelegate>

@end

Then, implement the timed search:

//
//  ViewController.m

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *textfield;
@property (strong, nonatomic) NSTimer * searchTimer;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // declare this view controller as the delegate
    self.textfield.delegate = self;

    // handle the change event (UIControlEventEditingChanged) by calling (textFieldDidChange:)
    [self.textfield addTarget:self
                  action:@selector(textFieldDidChange:)
        forControlEvents:UIControlEventEditingChanged];

}

// reset the search timer whenever the text field changes
-(void)textFieldDidChange :(UITextField *)textField{

    // if a timer is already active, prevent it from firing
    if (self.searchTimer != nil) {
        [self.searchTimer invalidate];
        self.searchTimer = nil;
    }

    // reschedule the search: in 1.0 second, call the searchForKeyword: method on the new textfield content
    self.searchTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0
                                                        target: self
                                                      selector: @selector(searchForKeyword:)
                                                      userInfo: self.textfield.text
                                                       repeats: NO];

}


- (void) searchForKeyword:(NSTimer *)timer
{
    // retrieve the keyword from user info
    NSString *keyword = (NSString*)timer.userInfo;

    // perform your search (stubbed here using NSLog)
    NSLog(@"Searching for keyword %@", keyword);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
TigerLily
  • 198
  • 1
  • 7
18

swift
xcode - 10

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool {
    NSObject.cancelPreviousPerformRequests(
        withTarget: self,
        selector: #selector(self.getHintsFromTextField),
        object: textField)
    self.perform(
        #selector(self.getHintsFromTextField),
        with: textField,
        afterDelay: 0.5)
    return true
}

@objc func getHintsFromTextField(textField: UITextField) {
    print("Hints for textField: \(textField)")
}

Witek Bobrowski
  • 3,749
  • 1
  • 20
  • 34
Abdul Karim
  • 4,359
  • 1
  • 40
  • 55
1

try this code:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSDate* timeStamp = [NSDate date];
    _timeStamp = timeStamp;
    CGFloat END_TYPING_TIME = 1.5;
    [self performSelector:@selector(endTyping:) withObject:timeStamp afterDelay:END_TYPING_TIME];
    return YES;
}

-(void) endTyping:(NSDate*) timeStamp {
    if ([timeStamp isEqualToDate:_timeStamp]) { //if it is the last typing...
        //TODO: do what ever you want to do at the end of typing...
    }
}

determine what is END_TYPING_TIME for your case...

the _timeStamp is a field of type NSDate.

Yedidya Reiss
  • 5,316
  • 2
  • 17
  • 19