Цель моего приложения - найти ближайших игроков Warhammer 40k. Координаты пользователей сохраняются в ветке Locations, которая имеет 4 дочерних ветки; «Начинающий», «Хороший», «Адепт», «Элит» .
После получения ключей (которые представляют собой пользовательские идентификаторы) для близлежащих координат система должна получить информацию о пользователях с помощью списка ключей (называемого distanceArray). После этого эта информация должна отображаться в tableView
.
Предполагается, что информация, которая должна отображаться о ближайших игроках: Изображение профиля, Имя, Средний рейтинг и количество оценок (Они хранятся в другой ветке) и Расстояние от вас.
Когда я запускаю fetchNearbyLocations в viewDidLoad()
, я не получаю никаких результатов в array
с именем distanceArray
. Я не получаю никаких результатов, пока я не перезагрузил tableView
2 раза. Как мне выбрать всех пользователей в начале?
Когда я использую настроенную мной кнопку перезагрузки, я получаю несколько копий уже присутствующих пользователей.
Важный код:
СТРУКТУРА И НАСТРОЙКА
var ref: DatabaseReference!
var GeoRef: GeoFire!
var users = [userList]()
var distanceArray = [tempDistance]()
let uid = Auth.auth().currentUser?.uid
var dbPath: String = "Beginner"
struct userList {
var name: String?
var databaseKey: String?
var imageUrl: String?
var distance: Double = 0
var avgRating: Double?
var ratingCount: Int?
}
struct tempDistance {
var uid: String?
var distanceToPrint: Double = 0
}
func fetchUsers() {
users.removeAll()
for item in distanceArray{
var name: String?
var databaseKey: String?
var imageUrl: String?
var distance: Double?
var avgRating: Double?
var ratingCount: Int?
checkName(userID: item.uid!, completion: { (success) -> Void in
if success{
let nameRef = self.ref.child("userInfo").child(item.uid!)
nameRef.observeSingleEvent(of: .value) { (snapshot) in
let dictionary = snapshot.value as? [String: AnyObject]
name = (dictionary!["Name"] as? String)!
imageUrl = (dictionary!["profileImage"] as? String)!
databaseKey = item.uid!
distance = item.distanceToPrint
self.users.append(userList(name: name, databaseKey: databaseKey, imageUrl: imageUrl, distance: distance!, avgRating: avgRating, ratingCount: ratingCount))
self.tableView.reloadData()
}
//Add retrieval for avgRating, and ratingCount
self.checkRatings(userID: item.uid!, completion: { (success) -> Void in
if success{
let avgRatingRef = self.ref.child("avgScore").child(item.uid!)
avgRatingRef.observeSingleEvent(of: .value) { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject]{
avgRating = (dictionary["Score"] as? Double)!
ratingCount = (dictionary["Count"] as? Int)!
}
print("append 1")
self.users.append(userList(name: name, databaseKey: databaseKey, imageUrl: imageUrl, distance: distance, avgRating: avgRating, ratingCount: ratingCount))
}
} else {
avgRating = 0
ratingCount = 0
print("append 2")
self.users.append(userList(name: name, databaseKey: databaseKey, imageUrl: imageUrl, distance: distance, avgRating: avgRating, ratingCount: ratingCount))
}
})
} else {
print("NAME AND IMAGE HAS NOT BEEN SET")
}
})
}
}
func fetchNearbyLocations (userID: String, dbPath: String) {
var keys = [String]()
var myLoc = CLLocation()
(self.GeoRef.getLocationForKey(userID, withCallback: { (location, error) in
if (error != nil) {
print("An error occured in fetchNearbyLocations: \(String(describing: error?.localizedDescription))")
}
else if (location != nil) {
myLoc = location!
//sets the radius - at 100 km
let circleQuery = self.GeoRef.query(at: myLoc, withRadius: 100.0)
circleQuery.observe(.keyEntered, with: { (key: String, location: CLLocation!) in
let distanceFromUser = myLoc.distance(from: location)
print("DISTANCE: \(distanceFromUser)")
keys.append(key)
self.distanceArray.append(tempDistance(uid: key, distanceToPrint: distanceFromUser))
print(self.distanceArray)
})
}
}))
}
//Reloads the arrays, acts as a refresh
@objc func reloadArray() {
fetchNearbyLocations(userID: uid!, dbPath: dbPath)
fetchUsers()
print(users)
print(distanceArray)
self.tableView.reloadData()
refreshControl.endRefreshing()
}
//sets the GeoRef to the needed value depending on the sorting
@objc func changeGeoRef() {
switch skillSortControl.selectedSegmentIndex {
case 0:
dbPath = "Beginner"
case 1:
dbPath = "Good"
case 2:
dbPath = "Adept"
case 3:
dbPath = "Elite"
default:
dbPath = "Beginner"
}
reloadArray()
GeoRef = GeoFire(firebaseRef: ref.child("Locations").child(dbPath))
}
// БЛОКИ ЗАВЕРШЕНИЯ
// CompletionBlock, чтобы проверить, есть ли у пользователя идентификатор пользователя
func checkName(userID: String, completion: @escaping ((_ success: Bool) -> Void)){
self.ref.child("userInfo").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.hasChild(userID){
completion(snapshot.hasChild(userID))
print("USERINFO EXISTS ")
//return true
}else{
print("NO USERDATA EXISTS")
completion(false)
//return false
}
//return result
}
)}
//completion block to check if user has any score, or rating
func checkRatings(userID: String, completion: @escaping ((_ success: Bool) -> Void)){
self.ref.child("avgScore").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.hasChild(userID){
completion(snapshot.hasChild(userID))
print("THERE EXISTS SOME RATINGS")
//return true
}else{
print("THERE IS NO RATING DATA, SETTING TO DEFAULT 0")
completion(false)
//return false
}
//return result
}
)}
// Функции табличного представления
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "searchProfileCell") as! SearchCell
cell.nameLabel.text = users[indexPath.row].name
let distanceInKm = users[indexPath.row].distance / 1000
let distanceStr = String(format: "%.1f", distanceInKm)
cell.distanceLabel.text = "\(distanceStr) km"
//sets the profile images to be round
cell.profileImage.layer.borderWidth = 1
cell.profileImage.layer.masksToBounds = false
cell.profileImage.layer.cornerRadius = cell.profileImage.frame.height/2
cell.profileImage.clipsToBounds = true
cell.profileImage.layer.borderColor = UIColor.black.cgColor
return cell
}