Функция Geofire / Firebase выполняет обработчик несколько раз в swift - PullRequest
0 голосов
/ 06 июня 2018

У меня есть следующая функция, которая выбирает список пользователей, использующих Geofire, а затем запрос Firebase во вложенной установке.

Сначала я выполняю запрос Geofire, чтобы получить key, а затем выполняю Firebaseзапросите и создайте объект User, который соответствует key, добавив User к массиву, который затем передается обратно через handler.

User array затем используется в CollectionView, проблема в том, что к моменту отображения CollectionView отображается только один User объект.

Я поместил несколько строк print() в коде для отладки и обнаружил, что функция передает данные через handler каждый раз, когда элемент добавляется, и, следовательно, число массивов к тому времени достигает значения VC, котороеCollectionView is 1.

Перемещение следующей строки за пределы for loop скобок пропускает пустую array

Как мне обновить мою функциютак что handler вызывается только один раз и проходит полный array?

handler(self.shuffleArray(array: filteredUsers) as! [User], true)

Вот функция:

    //Fetches all users currently at a Venue location of radius 50 metres
func getUsersAtVenue(forVenueLocation venueLocation: CLLocation, forUid uid: String, handler: @escaping (_ users: [User], _ success: Bool) -> ()){

    print("uid: \(uid)")

    var users = [User]()

    guard let currentLocation = LocationSingleton.sharedInstance.lastLocation else { return}//get current user's (device) location

    let distanceApart = round(10 * (venueLocation.distance(from: currentLocation) / 1000)) / 10 //get distance between currentLocation and venueLocation and convert from Mts to Kms rounding to 2 decimals

    if distanceApart <= 50 { //if distance apart if within 50kms then proceed

        let query = self.GEOFIRE_USERS_LOC.query(at: currentLocation, withRadius: 50)//radius in Kms

        query.observe(.keyEntered) { (key: String!, userLocation: CLLocation!) in

            print(key)

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

                guard let usersSnapshot = snapshot.children.allObjects as? [DataSnapshot] else { return }

                for user in usersSnapshot{

                    let discoverable = user.childSnapshot(forPath: "discoverable").value as! Bool

                    if user.key == key && discoverable == true {

                        let uid = user.key
                        let name = user.childSnapshot(forPath: "name").value as! String
                        let email = user.childSnapshot(forPath: "email").value as! String
                        let profilePictureURL = user.childSnapshot(forPath: "profilePictureURL").value as! String

                        let birthday = user.childSnapshot(forPath: "birthday").value as! String
                        let firstName = user.childSnapshot(forPath: "firstName").value as! String
                        let lastName = user.childSnapshot(forPath: "lastName").value as! String
                        let gender = user.childSnapshot(forPath: "gender").value as! String
                        let discoverable = user.childSnapshot(forPath: "discoverable").value as! Bool
                        let online = user.childSnapshot(forPath: "online").value as! Bool

                        let dictionary: [String : Any] = ["uid": uid, "name": name, "email": email, "profilePictureURL": profilePictureURL, "birthday": birthday, "firstName": firstName, "lastName": lastName, "gender": gender, "discoverable": discoverable, "online": online]

                        let user = User(uid: uid, dictionary: dictionary)

                        users.append(user)

                    }//end if

                }//end for

                //filter out current user from array
                let filteredUsers = users.filter({ (user: User) -> Bool in return !user.uid.contains(uid) })

                print("filteredUsers count: \(filteredUsers.count)")

                //handler passing a shuffled version of the array
                handler(self.shuffleArray(array: filteredUsers) as! [User], true)

            })//end FIR snapshot call

        }//end geoquery


    } else {//if distanace apart is NOT within 50kms then do this
        print("You're too far apart.")
        handler(users, false)
    }



}//end func

Консоль:

uid: dBQd541pxlRypR7l1WT2utKVxdX2
some("dBQd541pxlRypR7l1WT2utKVxdX5")
some("dBQd541pxlRypR7l1WT2utKVxdX3")
some("dBQd541pxlRypR7l1WT2utKVxdX2")
some("dBQd541pxlRypR7l1WT2utKVxdX4")
filteredUsers count: 1
users count: 1
filteredUsers count: 2
users count: 2
filteredUsers count: 2
users count: 2
filteredUsers count: 3
users count: 3

1 Ответ

0 голосов
/ 06 июня 2018

Событие .keyEntered запускается для каждого ключа, который находится или находится в пределах досягаемости вашего гео-запроса.Таким образом, изначально это означает, что он срабатывает для всех ключей в пределах диапазона, и с этого момента он будет срабатывать всякий раз, когда новый диапазон входит в диапазон (т.е. если вы добавляете нового пользователя в диапазон или если пользователь перемещается в диапазон).

Похоже, вы хотите определить, когда .keyEntered был вызван для всех начальных пользователей.Для этого вы можете наблюдать за готовым событием.

query.observeReadyWithBlock({
    //handler passing a shuffled version of the array
    handler(self.shuffleArray(array: filteredUsers) as! [User], true)
})

Если вы не заинтересованы в получении обновлений для новых / перемещающихся пользователей после первоначального запроса, это также отличный момент, чтобы удалить наблюдателя, позвонив по номеру removeObserverWithFirebaseHandle или removeAllObservers. * 1010.*

Также см. в ожидании «готовности» запросов в документации Geofire.

...