fredericdnd
fredericdnd

Reputation: 1008

GeoFire query completion - Swift

In my app, I use GeoFire to query users around user location. It is a Tinder-like app, with cards, etc... I use KolodaView for cards.

Query function :

func queryUsers(searchRadius: Int, center: CLLocation) {

    print("Query started")

    let geofireRef = Database.database().reference().child("usersLocations")
    let geoFire = GeoFire(firebaseRef: geofireRef)

    let circleQuery = geoFire?.query(at: center, withRadius: Double(searchRadius))

    _ = circleQuery?.observe(.keyEntered, with: { (result, location) in

        print("User \(result!) found")
        print("Adding user \(result!)")

        addUser(userID: result!, completionHandler: { (success) in

            print("User added")

        })

    })

}

Add user function :

func addUser(userID: String, completionHandler:@escaping (Bool) -> ()) {

    let foundUsers = UserDefaults.standard.array(forKey: "foundUsers")

    let databaseRef = Database.database().reference()

    databaseRef.observeSingleEvent(of: .value, with: { (snapshot) in

        if (foundUsers?.count)! < 20 {

            // USERS

            let users = (snapshot.value as? NSDictionary)?["users"] as! NSDictionary

            // USER

            let user = users[userID] as! NSDictionary

            getFirstUserPicture(userID: userID, completionHandler: { (data) in

                if let data = data {

                    DispatchQueue.main.async {

                        user.setValue(data, forKey: "picture")

                        // APPEND FOUND USERS ARRAY

                        var foundUsers = UserDefaults.standard.array(forKey: "foundUsers")

                        foundUsers?.append(user)

                        // STORE FOUND USERS ARRAY

                        UserDefaults.standard.set(foundUsers, forKey: "foundUsers")
                        UserDefaults.standard.synchronize()

                        // UPDATE CARD VIEW

                        if foundUsers?.count == 1 {

                            NotificationCenter.default.post(name: .loadCardView, object: nil)

                        } else {

                            NotificationCenter.default.post(name: .loadCardsInArray, object: nil)

                        }

                        // COMPLETION

                        completionHandler(true)

                    }

                }

            })

        }

    }) { (error) in

        print(error.localizedDescription)

    }

}

When I launch the app, the queryUsers function is called, the query starts

Output

User 1XXXXXXXXXXXXXXXX found
Adding user 1XXXXXXXXXXXXXXXX
User 2XXXXXXXXXXXXXXXX found
Adding user 2XXXXXXXXXXXXXXXX
User added
User added
  1. User is found
  2. Adding user (call addUser function)

The problem is that it didn't wait the addUser completion to call addUser for the second user found. The result is that in my KolodaView, there is the second user found two times because I think the call of addUser for the second user found uses first user found parameters.

Is it possible to wait for the first addUser completion and start again the query ? Or just "pause" the query after the first user was found, and start it again after the completion of the first addUser call ?

Thanks for your help

Update 1

I tried the @Rlee128 solution but nothing changed, I have the same output :( :

// MARK: UPDATE USER LOCATION - FUNCTION

func updateUserLocation() {

    let databaseRef = Database.database().reference().child("usersLocations")
    let geoFire = GeoFire(firebaseRef: databaseRef)

    let userID = UserDefaults.standard.string(forKey: "userID")!

    let locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.startUpdatingLocation()

    geoFire?.setLocation(locationManager.location, forKey: userID, withCompletionBlock: { (error) in

        if error != nil {

            print(error as Any)

        } else {

            // Location updated

        }

    })

}


// MARK: LOCATION MANAGER DELEGATE - FUNCTION

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

    manager.stopUpdatingLocation()
    manager.delegate = nil

}

Upvotes: 0

Views: 370

Answers (1)

Rlee128
Rlee128

Reputation: 117

In then location manger didUpdateLocations set manager.delegate to = nil after you call manager.stopUpdatingLocation(). Let me know if you want me to show you how it looks in my code.

func findLocation() {
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest

    locationManager.requestAlwaysAuthorization()

    if CLLocationManager.locationServicesEnabled() {
        locationManager.startUpdatingLocation()
    }
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let userLocation = locations[0] as CLLocation
    manager.stopUpdatingLocation()
    manager.delegate = nil
    let loc = CLLocation(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
    getLocation(location: loc)

}

Upvotes: 1

Related Questions