0

On my main CollectionView (the app home page), I would like to update the locations (i.e. the cells themselves) based on the closest location to the user. I am storing my locations in Firebase and will be using GeoFire and core location in order to properly list out the locations in distance order from the user.

Other posts have said that the best practice for observers involves loading it in viewWillAppear; however, I have been unable to obtain the user's location before this runs and do not have a centered point for my GeoFire query. Most examples related to CoreLocation involve maps or preselected coordinates, but I wasn't planning on using a map within this controller and want to dynamically load based off of user location.

I have researched loading didUpdateLocations within AppDelegate, but have not been able to call that method there either. What is the best way to get user location coordinates before running a GeoFire query when loading that returned data in viewWillAppear or do you need to set a region and check if a user has entered within that region?

    var locationDict = [CLLocation]()  //using this variable to pass values outside the function to the query        
    override func viewWillAppear(animated: Bool) {
         locationManager.desiredAccuracy = kCLLocationAccuracyBest
         locationManager.requestAlwaysAuthorization()
         locationManager.startUpdatingLocation()
    }


    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let recentLocation = locations[0]
     locationDict.append(recentLocation)     
  }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {

        print(error.localizedDescription)

}
nynohu
  • 1,628
  • 12
  • 12
Josh
  • 7
  • 4
  • I had the same problem, solved it by getting the location in viewWillAppear & the observer in viewDidAppear. Also I checked if my location was valid before querying firebase. – Peter de Vries Jan 10 '17 at 13:46
  • How would you get the location from Core Location in viewWillAppear itself? Would I need to use the location manager method of .requestLocation? could you show me basic code of how you overcame that problem? – Josh Jan 10 '17 at 23:24

1 Answers1

0

There is quite a lot missing in your code, but in short (what works for me):

.requestLocation in viewWillAppear

.startUpdatingLocation() in viewDidAppear. (so twice).

var justStartedUsingMap = true

In didUpdateLocations:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){

    guard let myLocation:CLLocation = manager.location else {return}
    let location:CLLocationCoordinate2D = myLocation.coordinate
    let region = MKCoordinateRegion(center: location, span: MKCoordinateSpan(latitudeDelta: 0.12, longitudeDelta: 0.12))

    if justStartedUsingMap == true {
        self.currentLocationSearch(myLocation)
        justStartedUsingMap = false
    } else {
        locationManager.stopUpdatingLocation()
    }

    self.map.setRegion(region, animated: true)
}

func currentLocationSearch(_ location: CLLocation) {
    // the geofire observer 
}
Peter de Vries
  • 780
  • 1
  • 6
  • 14
  • From your question on this [http://stackoverflow.com/questions/41449938/how-to-remove-a-geofire-handle-for-the-following-observe-in-swift] how do I properly remove the handle for GeoFire in Swift 3 since the documentation doesn't seem to be updated. When you use `locationManager.location` is that only pulling the coordinates once? – Josh Jan 12 '17 at 05:56
  • @Josh No it will continue to pull coordinates, therefore I put in a var justStartedUsingMap = true, and put if justStartedUsingMap = true { if self.locationsIndex == 0 //etc justStartedUsingMap = false} else {locationManager.stopUpdatingLocation()}, hesitate to put that in the answer, as I read somewhere you shouldn't do that. Also yes the answer by Jay removes the handle, but as soon as you move around on the map and the observer needs to find new objects in the vicinity, the observer does not get released on viewDidDisappear. I narrowed that down to the observer. – Peter de Vries Jan 12 '17 at 09:40
  • Yeah my main issue now is that occasionally and I am not sure why the location is returned one to many times and then causes duplication of my UI when returning to this view controller. Do you think I should conditionally check if my local array is equal to a specific count and if not delete older location values? – Josh Jan 12 '17 at 15:17
  • not sure why you want all of your locations in a localDict, if you just need your one location, which you'd get from: if self.locationsIndex == 0 { self.currentLocationSearch(myLocation) }. – Peter de Vries Jan 12 '17 at 19:34
  • What is locationsIndex? A variable tracking the amount of location coordinates that have been stored? – Josh Jan 12 '17 at 20:22
  • updated answer, took out the self.locationsIndex, which is not relevant. hope that helps – Peter de Vries Jan 12 '17 at 21:07