Reputation: 8490
I have a UISearchBar
and UISearchDisplayController
. When the user writes text in it inside searchBar:textDidChange:
I make a web-service call to filter my TableView. The problem is that the GUI get unresponsive until I get the result from the web-service. I've tried to solve it using [self performSelector:@selector(callWebService:) withObject:searchText];
, but it's still unresponsive.
EDIT: Following Flink advice, I changed performSelector
to performSelectorInBackground
, but now the tableView doesn't filter correctly, it only show 'No Results'.
even tableView:numberOfRowsInSection:
isn't get called.
EDIT Again: The reason I got 'No Results' was due to not calling reloadData
on the correct tableView. UISearchDisplayController
has a property named searchResultsTableView
. So in the end what I used was [self.searchDisplayController.searchResultsTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:false];
and now it works fine.
It should be noted that although I chose the performSelectorInBackground
, I probably should have tried to use sendAsynchronousRequest
method on NSURLConnection
- See AliSoftware's answer.
Upvotes: 1
Views: 1122
Reputation: 32681
You should avoid creating a background queue or thread to perform your network request(which is what performSelectorInBackground:
does) as this creates a worker thread just for this which is not as efficient as scheduling the request on the NSRunLoop
.
Dedication a thread will make the processor activate the thread regularly to check if there are some data, and creating a thread for that is quite overkill. Scheduling the request on the run loop (as a run loop source) will use network interruptions to signal incoming data from the socket and thus will only be activated when there is actual data available.
To do this, simply use the asynchronous methods provided by NSURLConnection
.
NSURLConnection
(this is the old way to do it, the only way that was available in the NSURLConnection
API back in iOs3)Another more modern solution is to use the block API provided by NSURLConnection
which is easier to use and code.
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse* response, NSData* receivedData, NSError* error)
{
// Your code to execute when the network request has completed
// and returned a response (or timed out or encountered an error)
// This code will execute asynchronously only once the whole data is available
// (the rest of the code in the main thread won't be blocked waiting for it)
}];
// After this line of code, the request is executed in the background (scheduled on the run loop)
// and the rest of the code will continue: the main thread will not be frozen during the request.
Read more in the URL Loading System Programming Guide and in the NSURLConnection
class reference.
Upvotes: 1
Reputation: 16664
You need to make your web call async.
In your case, you can change performSelector
to performSelectorInBackground
Upvotes: 1