UISearchBar detect when user stop type in swift
Asked Answered
A

6

9

Most of the example I found is in Objective - C which is very hard for me to understand can someone provide an example regarding this question in Swift. Here is one solution but it is in Objective C.

Alpert answered 9/12, 2016 at 11:29 Comment(7)
Ask more clearly so that someone can understand!! you can share link link of objective c that you have mentioned!Marshallmarshallese
Ok i will edit my question.Alpert
Did you try searchBarTextDidEndEditing and searchBarShouldEndEditing ??Peruke
While user typing side by side search proceed, Is it? For this you have to make custom search bar.Karolynkaron
Why u want to do this , it will degrade your application performanceRenounce
@SandeepBhandari yes I have already tried using it but can't find solution using those override functions.Alpert
@Karolynkaron No I just want to detect the action after when user stops typing .Alpert
A
14
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    print("after every text gets changed")
    timer.invalidate()
    timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: #selector(ViewController.output), userInfo: searchText, repeats: false)
}

func output(){
    print("hello")
    if timer.userInfo != nil {
        print(timer.userInfo)
    }
    timer.invalidate()
}
Alpert answered 12/12, 2016 at 9:32 Comment(2)
This is how i solved my problem... Thank you everyone for your kind suggestion :)Alpert
Very smart solution. I was looking for async function and how to kill previous async task. This one is much easier and intuitive. Thanks.Courser
O
8

Swift 5

Throttled search

Use NSObject.cancelPreviousPerformRequests to cancel previous triggers.

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(ViewController.reload), object: nil)
    self.perform(#selector(ViewController.reload), with: nil, afterDelay: 0.5)
}
    
@objc func reload() {
    guard let searchText = searchBar.text else { return }
    search(searchText)
}
Orogeny answered 1/7, 2019 at 10:43 Comment(0)
P
3

You could try this:

class WorkItem {

private var pendingRequestWorkItem: DispatchWorkItem?

func perform(after: TimeInterval, _ block: @escaping () -> Void) {
    // Cancel the currently pending item
    pendingRequestWorkItem?.cancel()

    // Wrap our request in a work item
    let requestWorkItem = DispatchWorkItem(block: block)

    pendingRequestWorkItem = requestWorkItem

    DispatchQueue.main.asyncAfter(deadline: .now() + after, execute: requestWorkItem)
}
}

// to use

lazy var workItem = WorkItem()

func searchBar(_ searchBar: UISearchBar, textDidChange: String) {

    // 0.5 == half second
    workItem.perform(after: 0.5) {

       //Have Stopped, do something.
    }
}

References

Link 1 by swiftbysundell

Link 2 on github

Petaloid answered 8/1, 2019 at 17:17 Comment(1)
Edited, just replace it by () -> VoidPetaloid
K
2

Swift version of your link:

var searchDelayer: Timer!

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    searchDelayer.invalidate(), searchDelayer = nil
    if true {
        searchDelayer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(self.doDelayedSearch), userInfo: searchText, repeats: false)
    }
}

func doDelayedSearch(_ t: Timer) {
    assert(t == searchDelayer)
    self.request(searchDelayer.userInfo!)
    searchDelayer = nil
}




var priorSearchText = ""

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(self.request), object: priorSearchText)
        priorSearchText = searchText
    }
    if true {
        self.performSelector(#selector(self.request), withObject: searchText, afterDelay: 1.5)
    }
Karolynkaron answered 9/12, 2016 at 11:42 Comment(1)
Am I right that here you showed us two different ways to perform this task?Mudd
G
1

You have to check it using UISearchBarDelegate:

func searchBarTextDidEndEditing(searchBar: UISearchBar) {
    //DO what you want
}

Remember to add:

searchBar.delegate = self

And his relative protocol:

UISearchBarDelegate

https://developer.apple.com/reference/uikit/uisearchbardelegate

That delegate : searchBarTextDidEndEditing is called when the keyboard disappears, so add that code to your proj:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    self.view.endEditing(true)
}
Glabrescent answered 9/12, 2016 at 11:37 Comment(5)
func searchBarTextDidEndEditing(searchBar: UISearchBar) { print("Type End"); } Initially I have done the same thing but after when type is end the value is not printed in console so i assume this does not work.Alpert
You have to add: searchBar.delegate = selfGlabrescent
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. /* Setup delegates */ tableView.delegate = self tableView.dataSource = self searchBar.delegate = self } Yes i have mention that already.Alpert
check out the new answerGlabrescent
This is not good answer. He doesn't want to dismiss keyboard, he just wants to inform system that he has stoped typing.Slimsy
U
0
var timer: Timer?
            
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    guard let text = searchBar.text else { return }
    timer.invalidate()
    timer = Timer.scheduledTimer(withTimeInterval: 0.7, repeats: false, block: { _ in
        print(text)
    })
}
        
Uncharitable answered 7/2, 2023 at 12:56 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Jeraldinejeralee

© 2022 - 2025 — McMap. All rights reserved.