2

I'm using UISearchController for searching in an array of 86,111 objects (actually I'm searching in the name property of each object).

For some reason, when I start typing on the search bar, the UI freezes for a couple of seconds and then starts working again (for example, the keyboard freezes on one letter, etc.).

I think it's because my UI is really big - I can understand why it's searching very slowly, but I can't understand why it's freezing the UI (isn't it searching on a background thread?).

I'll be really happy if someone will be able to help me,

Thank you!

FS.O
  • 403
  • 6
  • 24

2 Answers2

2

Most likely your actual search (through all your objects) happens on the main thread. UISearchController has nothing to do with threads, it lets the programmer implement that part, so this is why you are using the main thread for the search. I don't know how you implemented all this but you should use dispatch_async or NSOperationQueue to perform the search on a background thread.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   //Code to perform the search
   dispatch_async(dispatch_get_main_queue(), ^{
      //Set the results of the search in the UI
   });
});

See this answer about switching between threads.

Community
  • 1
  • 1
Jelly
  • 4,522
  • 6
  • 26
  • 42
  • I've tried to use `NSOperationQueue` on my `searchResults` array's setter but how can I `return` the array on a background thread? – FS.O Apr 09 '16 at 06:22
  • If you are using `NSOperationQueue` you could run code back on the main using `[NSOperationQueue mainQueue]`. I also updated my answer with some basic sample with `dispatch_async` – Jelly Apr 09 '16 at 06:25
  • Yes I know, but when `searchResults`'s getter is being called (where I filter the array using `NSPredicate`) I need to return the array, but if it's on a background thread, how can I return the correct and updated array? – FS.O Apr 09 '16 at 06:29
  • You can't `return`. You have to use a `block` to execute what you need (update UI) when the search finishes. If you would return it the main thread would have to wait for the background one to finish, which would keep it blocked defeating the whole purpose of having a background thread. – Jelly Apr 09 '16 at 06:40
0

I think you can perform your search in the background thread by using GCD(Grand Central Dispatch). Then, you can move your code part that updates UI into the dispatch_async block because UI update should be done in the main thread.

If you use dispatch queue in swift, you can write code like this.

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)   

dispatch_async(queue) { () -> Void in

    let resultArray = Search()

    dispatch_async(dispatch_get_main_queue(), {
        UI_Update()
    })
}

If you use NSOperation queue, I think this code will work.

queue = NSOperationQueue()

queue.addOperationWithBlock { () -> Void in

    let resultArray = Search()

    NSOperationQueue.mainQueue().addOperationWithBlock({
        UI_Update()
    })
}
woogii
  • 413
  • 3
  • 11
  • I've tried to use `NSOperationQueue` on my `searchResults` array's setter but how can I `return` the array on a background thread? – FS.O Apr 09 '16 at 06:24