Search code examples
iosmultithreadingswiftmapkitreloaddata

reloadData doesn't reload the table view in completion handler's dispatch_async to the main thread


I'm using a UISearchBar to do a MKLocalSearch with Swift 1.2 in iOS 8 (simulator).

I get the results returned in the completion handler (see it in the console via printlns), but when I try to do an async call the main thread to reload the table view nothing happens.

If I click cancel in the search bar it will then show the results in the table view. It seem that I'm doing the async reload data call wrong.

Here is my code for the UISearchBarDelegate searchBarSearchButtonClicked:

func searchBarSearchButtonClicked(searchBar: UISearchBar) {
    searchBar.resignFirstResponder()

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    if let currentLocation = appDelegate.currentLocation {
        searchResults.removeAll()

        let request = MKLocalSearchRequest()
        request.naturalLanguageQuery = searchBar.text
        request.region = MKCoordinateRegionMakeWithDistance(currentLocation.coordinate, 200, 200)

        let search = MKLocalSearch(request: request)

        search.startWithCompletionHandler({ (response: MKLocalSearchResponse!, error: NSError!) -> Void in
            if error != nil {
                println("Error occured in search: \(error.localizedDescription)")
            } else if response.mapItems.count == 0 {
                println("No matches found")
            } else {
                println("Matches found")

                for item in response.mapItems as! [MKMapItem] {
                    println("Name = \(item.name)")

                    self.searchResults.append(item)
                }

                println("Matching items = \(self.searchResults.count)")
            }

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.searchTableView.reloadData() // doesn't do anything
            })
        })
    }

}

Here is an example of what I am seeing in the console, but with a still empty table view:

numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
numberOfRowsInSection called
searchBarSearchButtonClicked called
startWithCompletionHandler called
Matches found
Name = Artichoke Basille's Pizza
Name = Scott's Pizza Tours
Name = Waldy's Wood Fired Pizza & Penne
Name = Trattoria Zero Otto Nove
Name = Vezzo Thin Crust Pizza
Name = Grimaldi's
Name = Tappo Thin Crust Pizza
Name = Mozzarelli's
Name = NY Pizza Suprema
Name = Otto Enoteca Pizzeria
Matching items = 10
numberOfRowsInSection called
cellForRowAtIndexPath called, name = Artichoke Basille's Pizza
cellForRowAtIndexPath called, name = Scott's Pizza Tours
cellForRowAtIndexPath called, name = Waldy's Wood Fired Pizza & Penne
cellForRowAtIndexPath called, name = Trattoria Zero Otto Nove
cellForRowAtIndexPath called, name = Vezzo Thin Crust Pizza
cellForRowAtIndexPath called, name = Grimaldi's
cellForRowAtIndexPath called, name = Tappo Thin Crust Pizza
cellForRowAtIndexPath called, name = Mozzarelli's
cellForRowAtIndexPath called, name = NY Pizza Suprema
cellForRowAtIndexPath called, name = Otto Enoteca Pizzeria

What am I doing wrong here?

Thanks!

EDIT: added some more printlns to show the different table delegate methods were being called and updated the console output above.


Solution

  • OK, so your log would appear to show that cellForRowAtIndexPath is getting called properly and that it's successfully retrieving the data. So, now the question is why you're not seeing it in the table.

    Either cellForRowAtIndexPath isn't populating the right controls, or the frame (or alpha or something like that) for those controls are set such that you can't see the data. Pause execution by hitting the "pause" button in Xcode:

    enter image description here

    and look at the layout of the views, either in the new view debugger:

    enter image description here

    or by typing po [[UIWindow keyWindow] recursiveDescription] at the (lldb) prompt. Confirm the frame of the the text label that you're populating with the data that you logged.