0

The location manager takes a while to query through a class of 10000 rows (in Parse). I'm trying to prevent the user from selecting a row (in tableViewController) before the query finishes. What is the optimal way to force the user to wait for the query to complete before allowing the selection?

Query to Load Data:

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: { (placemarks, error) -> Void in
        if (error != nil) {
            println("Error:" + error.localizedDescription)
        }
        if placemarks.count > 0 {
            let pm = placemarks[0] as CLPlacemark
            self.displayLocationInfo(pm)
            currentLoc = manager.location
            currentLocGeoPoint = PFGeoPoint(location:currentLoc)

            var query = PFQuery(className:"test10000")
            query.whereKey("RestaurantLoc", nearGeoPoint:currentLocGeoPoint, withinMiles:10) //filter by miles
            query.limit = 1000 //limit number of results
            query.findObjectsInBackgroundWithBlock {
                (objects: [AnyObject]!, error: NSError!) -> Void in
                if objects != nil {
                    unfilteredRestaurantArray = objects
                } else {
                    println("error: \(error)")
                }
            }

        } else {
            println("error: \(error)")
        }
    })
}

Additional Info:

The program uses didSelectRowAtIndex with segues:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if indexPath.row == 0 {
        self.performSegueWithIdentifier("toQ2", sender: self)
    } else {
        self.performSegueWithIdentifier("toQ1", sender: self)
    }

viewDidLoad calls the locationManager:

override func viewDidLoad() {
    self.locationManager.delegate = self //location manager start
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
    self.locationManager.requestWhenInUseAuthorization()
    self.locationManager.startUpdatingLocation()
}
Onichan
  • 4,476
  • 6
  • 31
  • 60

1 Answers1

1

Define yourself a variable which indicates, that the query is still running. When you start the query, disable any interactions with the table or place an overlay with an activity indicator on it. To get notified when the query is done you can use didSet hook, e.g.

var queryIsRunning : Bool { didSet { onQueryIsRunningChanged() } }

[...]

func onQueryIsRunningChanged()
{
    if queryIsRunning
    {
        // Code to disable user interactions
    }
    else
    {
        // Code to re-enable user interactions
    }
}

Maybe it is necessary to set the variable from the main thread, this can be accomplished by

dispatch_async(dispatch_get_main_queue(), { self.queryIsRunning = queryIsRunningState } )
Sebastian
  • 8,046
  • 2
  • 34
  • 58
  • thanks for the answer. is it sufficient to use `queryIsRunning = false//true`, or do I need to use the didSet hook? – Onichan Jan 11 '15 at 10:50
  • Also, would you mind explaining what the dispatch_async is used for and where I would place it? Thanks in advanced :) – Onichan Jan 11 '15 at 10:50
  • Variable: You just assign to `queryIsRunning` and the hook does the call automatically. Dispatch: assuming your query runs in another thread, but the table uses the main thread, the `dispatch_async` ensures, that the hook will be executed on the main thread. This is not needed, if query and table are using the same thread. – Sebastian Jan 11 '15 at 10:52
  • Ok I understand. However, I keep producing an error when adding the `queryIsRunning` block. http://i.imgur.com/qAgkz4L.png Did I implement this wrong? – Onichan Jan 11 '15 at 11:00
  • 1
    That is because the variable is not initialised. You have to implement init functions, also for NSCoding (see [Swift: Class does not implement its superclass's required members](http://stackoverflow.com/q/25126295/172695)). You can circumvent this by initializing the variable directly, e.g. `var queryIsRunning : Bool = false { ... }` – Sebastian Jan 11 '15 at 11:05
  • I've been playing around with this for a while but ran into an issue where the activity indicator does not hide at the end of the code block. I even tried implementing other forms of the same code: http://stackoverflow.com/questions/27928249/activity-indicator-not-hiding – Onichan Jan 14 '15 at 00:33