3

I'am trying to query an array of PFGeoPoints stored on the Parse backend. I have the User table, with data assigned to it such as "location", "name". everything is being sent to Parse upon posting from my app and is properly stored in the backend. I am having issues retrieving all location from Parse and storing them into an MKAnnotation on the map. Find below my code

import UIKit
import Parse
import CoreLocation
import MapKit

class mapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
    @IBOutlet var mapUsers: MKMapView!
    var MapViewLocationManager:CLLocationManager! = CLLocationManager()
    var currentLoc: PFGeoPoint! = PFGeoPoint()
    

    override func viewDidLoad() {
        super.viewDidLoad()
        // ask user for their position in the map
        
        PFGeoPoint.geoPointForCurrentLocationInBackground {
            
            (geoPoint: PFGeoPoint?, error: NSError?) -> Void in
            
            if let geoPoint = geoPoint {
                
                PFUser.currentUser()? ["location"] = geoPoint
                PFUser.currentUser()?.save()
             }
        }
    
    mapUsers.showsUserLocation = true
    mapUsers.delegate = self
    MapViewLocationManager.delegate = self
    MapViewLocationManager.startUpdatingLocation()
    mapUsers.setUserTrackingMode(MKUserTrackingMode.Follow, animated: false)
  
    }
    
    override func viewDidAppear(animated: Bool) {
    
        let annotationQuery = PFQuery(className: "User")
       
        currentLoc = PFGeoPoint(location: MapViewLocationManager.location)
        
        annotationQuery.whereKey("Location", nearGeoPoint: currentLoc, withinMiles: 10)
       
        annotationQuery.findObjectsInBackgroundWithBlock {
            (PFUser, error) -> Void in
            
            if error == nil {
                
                // The find succeeded.
            
                print("Successful query for annotations")
                
                let myUsers = PFUser as! [PFObject]
                
                for users in myUsers {
                    let point = users["Location"] as! PFGeoPoint
                    let annotation = MKPointAnnotation()
                    annotation.coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude)
                    self.mapUsers.addAnnotation(annotation)
                }
            } else {
                // Log details of the failure
                print("Error: \(error)")
            }
        }
    }
Wain
  • 118,658
  • 15
  • 128
  • 151
Mams1101
  • 53
  • 9
  • what happens if you try to query on the locations stored in the parse class using this? PFGeoPoint *userLocation = [PFGeoPoint geoPointWithLatitude:currentLocation.coordinate.latitude longitude:currentLocation.coordinate.longitude]; [query whereKey:@"location" nearGeoPoint:userLocation withinKilometers:radius]; – Henry Situ Oct 30 '15 at 07:52
  • 1
    I have more knowledge in swift... Can you update your answer with swift language please ! – Mams1101 Oct 30 '15 at 08:29
  • 2
    Code looks reasonable, but you don't know that `MapViewLocationManager.location` is good / valid when you try to use it - what is it? – Wain Oct 30 '15 at 11:20
  • 1
    Exactly what @Wain said. Let us know what the output is when you run it and if you are getting any results from the query. It's possible that `MapViewLocationManager.location` is nil which will in turn make the query have no results, leading to 0 annotations on the map – Russell Oct 30 '15 at 16:14
  • @Mams1101 how does this answer work for you from http://stackoverflow.com/questions/30828847/how-to-retrive-location-from-a-pfgeopoint-parse-com-and-swift-and-show-it-on ? Also more details available at http://blog.parse.com/2014/09/18/parse-sdk-for-ios-8-performance-and-security/ and https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/instm/CLLocationManager/requestAlwaysAuthorization – Henry Situ Oct 30 '15 at 16:19

1 Answers1

1

Instead of putting the call in your viewDidAppear() method - as previous commenters said, your location may be nil, returning no results - I would use a tracker of some sort and put it in your didUpdateLocations() MKMapView delegate method. Here, I use GCD's dispatch_once() so that when my location is found for the first time with a reasonable accuracy, my code is executed (here you will put your call to Parse).

Declare GCD's tracker variable

var foundLocation: dispatch_once_t = 0

Now use something like this in your location manager's delegate method didUpdateLocations()

    if userLocation?.location?.horizontalAccuracy < 2001 {
        dispatch_once(&foundLocation, {
            // Put your call to Parse here
        })
    }

PS. You should also consider doing any updates to UI on the main thread. Parse fetches that data on a background thread and although you might never see a problem, it's both safer and good habit to do any UI changes on main thread. You can do this with the following:

dispatch_async(dispatch_get_main_queue(), {
    // Put any UI update code here. For example your pin adding
}
Byron Coetsee
  • 3,533
  • 5
  • 20
  • 31