Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect when stopped typing in UITextField

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.

like image 706
Max Avatar asked Jul 05 '15 04:07

Max


3 Answers

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

}
like image 62
ThetNaing Mizo Avatar answered Oct 22 '22 19:10

ThetNaing Mizo


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
like image 18
TigerLily Avatar answered Oct 22 '22 19:10

TigerLily


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

like image 17
Abdul Karim Avatar answered Oct 22 '22 21:10

Abdul Karim