一旦坐标在 Firebase 中保存为字符串,如何在 CLLLoationDegrees 中获取它们来计算用户之间的距离?
Posted
技术标签:
【中文标题】一旦坐标在 Firebase 中保存为字符串,如何在 CLLLoationDegrees 中获取它们来计算用户之间的距离?【英文标题】:Once coordinates are saved as String in Firebase, how are they fetched in CLLLoationDegrees to calculate the distance between users? 【发布时间】:2019-07-09 09:09:44 【问题描述】:我认为应该这样做:
1 在 Firebase 中创建所有用户坐标经度和纬度条目的快照 - 在输出框中打印出来以检查此步骤。
2.1 命名一个函数,用于计算登录用户与所有其他用户之间的距离
2.2 在该函数中 make let coordinate₀ = 登录用户的坐标。数据库具有坐标的字符串值,因此需要以某种方式将其设置为 CLLLoationDegrees。
2.3 为坐标1创建一个循环,直到坐标X(即数据库中的所有用户)为其坐标
2.4 使用 let distanceInMeters = coordinate₀.distance(from: coordinate₁) 并循环所有距离,直到坐标X(数据库中的最后一个)
2.5 打印输出框中的所有距离。 (我不需要将它们打印在应用程序上,我只是获取距离,以便按距离对用户进行排名)
The Database looks like this for each kid:
"people" :
"2jWm6rUfZVYAGkSST0fvVvwolY92" :
"Coordinates" :
"latitude" : 45.785834,
"longitude" : -100.406417
,
"Education" : "BA Arts",
"PhotoPosts" : "https://firebasestorage.googleapis.com/v0/b/westpluto1.appspot.com/o/images%2FPhotoPosts?alt=media&token=ccd5a139-b3e1-4ac9-965c-2f09c149fc74",
"users" : "jackmaster1091@aol.com"
,
///Part A
var refArtists : DatabaseReference!
var people = [Userx]()
var latestLocation: [String: Double]? ////this double was added to get coordinates into firebase under longitude and latitude
///B部分
let thisUsersUid = Auth.auth().currentUser?.uid //Mr. Dunn's uid
refArtists = Database.database().reference().child("people");
refArtists.observe(DataEventType.value, with: snapshot in
if snapshot.childrenCount>0
self.people.removeAll()
for people in snapshot.children.allObjects as! [DataSnapshot]
if people.key != thisUsersUid //do not add this users info to the array
let peopleObject = people.value as? [String: AnyObject]
let peopleCoordinates = peopleObject?["Coordinates"] as? String
let peopl = Userx(Coordinates: peopleCoordinates)
self.people.append(peopl)
self.table.reloadData()
print(snapshot)
)
///C部分
func distance ()
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
let coordinate₀ = CLLocation(latitude: databaseRef.child("people").child(uid).child("Coordinates").child("latitude"), longitude: databaseRef.child("people").child(uid).child("Coordinates").child("longitude")) //////I think this is incorrect even w/o string to CLL conversion because I don’t think longitude and latitude and technically children of Coordinates
…..
let distanceInMeters = coordinate₀.distance(from: coordinate₁)
let distanceInMeters2 = coordinate₀.distance(from: coordinate2)
….
Print …
Print …
///////代码基于 Jay 的回答
let uid = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("people").child(uid).child("Coordinates")
ref.observeSingleEvent(of: .value, with: snapshot in
let allCoordinates = snapshot.children.allObjects as! [DataSnapshot]
for Coordinates in allCoordinates
let lat = Coordinates.childSnapshot(forPath: "latitude").value as! CLLocationDegrees
let lon = Coordinates.childSnapshot(forPath: "longitude").value as! CLLocationDegrees
let userId = Coordinates.key
let locCoord = CLLocationCoordinate2DMake(lat, lon)
let bcoordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
)
///第二次更新代码:
let uid = Auth.auth().currentUser!.uid
refArtists = Database.database().reference().child("people");
let ref = self.refArtists.child(uid).child("Coordinates")
ref.observeSingleEvent(of: .value, with: snapshot in
let allLocations = snapshot.children.allObjects as! [DataSnapshot]
for location in allLocations
let userId = location.key
let coordSnap = location.childSnapshot(forPath: "Coordinates")
let lat = coordSnap.childSnapshot(forPath: "latitude").value as! CLLocationDegrees
let lon = coordSnap.childSnapshot(forPath: "longitude").value as! CLLocationDegrees
let locCoord = CLLocationCoordinate2DMake(lat, lon)
let coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
print(" coords: \(lat) \(lon)")
)
////这是现在打印两个坐标的代码:
let ref = self.refArtists.child(uid).child("Coordinates")
ref.observeSingleEvent(of: .value, with: snapshot in
let allLocations = snapshot.children.allObjects as! [DataSnapshot]
for location in allLocations
let userId = location.key
let lat = snapshot.childSnapshot(forPath: "latitude").value as! CLLocationDegrees
let lon = snapshot.childSnapshot(forPath: "longitude").value as! CLLocationDegrees
let locCoord = CLLocationCoordinate2DMake(lat, lon)
let coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
print(" coords: \(lat) \(lon)")
我希望在这一切之后根据位置对用户进行排名。
【问题讨论】:
CLLocationDegrees 可能应该存储为双精度,然后您可以读取它们并像这样直接分配它们`let coord = CLLocationCoordinate2DMake(lat, lon)'。有关工作代码,请参阅this question 的答案。我不明白问题的其余部分在问什么。 谢谢。是的,它存储为双精度数。您链接的代码有意义但给出错误:“任何?”不能转换为 '[String : AnyObject]';你的意思是用'as!'强制向下转换?”你知道如何解决这个问题吗?我认为这是 Xcode 版本类型的错误。我当然将“位置”更改为我在 firebase 中设置的内容。 是的 - 此时问题中的代码已经使用了三年,并且没有针对 swift 5 进行更新。我发布了一个答案,让您朝着正确的方向前进。 谢谢!我会试试的。 【参考方案1】:有多种方法可以读取您询问的数据。以下是每个的摘要
选项 1)
如果有一系列节点直接在节点内存储坐标数据
people
uid_0
Latitude: xxxxxxxx
Longitude: yyyyyyy
uid_1
Latitude: aaaaaaaa
Longitude: bbbbbbbb
并且您想遍历每个节点并为每个位置节点(loc_0、loc_1 或 uid_0 uid_1 等)创建一个 CoreLocation 对象,这是执行此操作的代码。
let ref = self.ref.child("people")
ref.observeSingleEvent(of: .value, with: snapshot in
let allUsers = snapshot.children.allObjects as! [DataSnapshot]
for user in allUsers
let lat = user.childSnapshot(forPath: "Latitude").value as! CLLocationDegrees
let lon = user.childSnapshot(forPath: "Longitude").value as! CLLocationDegrees
let userId = user.key
let locCoord = CLLocationCoordinate2DMake(lat, lon)
let coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
)
注意 self.ref 指向我的 Firebase 根目录。
选项 2)
如果您的 Firebase 结构的坐标数据存储在每个父节点下的 Coordinates 节点中,则将 Coordinates 节点视为它自己的快照,这样您就可以访问它的两个子坐标,lat 和 lon。
people
uid_0
name: "some user"
coordinates:
Latitude: 1
Longitude: 2
uid_1
name: "another user"
coordinates:
Latitude: 3
Longitude: 4
请注意,我添加了一个名称子节点,因此您也可以查看如何读取它。
let ref = self.ref.child("people")
ref.observeSingleEvent(of: .value, with: snapshot in
let allUsers = snapshot.children.allObjects as! [DataSnapshot]
for user in allUsers
let userName = user.childSnapshot(forPath: "name").value as! String
let userId = user.key
let coordSnap = user.childSnapshot(forPath: "coordinates")
let lat = coordSnap.childSnapshot(forPath: "Latitude").value as! CLLocationDegrees
let lon = coordSnap.childSnapshot(forPath: "Longitude").value as! CLLocationDegrees
let locCoord = CLLocationCoordinate2DMake(lat, lon)
let coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
print("uid: \(userId) name: \(userName)")
print(" coords: \(lat) \(lon)")
)
输出将如下所示
uid: uid_0 name: some name
coords: 1.0 2.0
uid: uid_1 name: another name
coords: 3.0 4.0
选项 3)
如果您想读取单个特定节点而不是遍历所有节点,代码如下。您需要知道父节点的路径,在这种情况下是当前用户的 uid。
func readThisUsersCoordinates()
let uid = Auth.auth().currentUser!.uid
let peopleRef = Database.database().reference().child("people");
let thisPersonRef = peopleRef.child(uid)
let thisPersonCoordsRef = thisPersonRef.child("Coordinates")
thisPersonCoordsRef.observeSingleEvent(of: .value, with: snapshot in
let lat = snapshot.childSnapshot(forPath: "latitude").value as! CLLocationDegrees
let lon = snapshot.childSnapshot(forPath: "longitude").value as! CLLocationDegrees
print(" coords: \(lat) \(lon)")
)
【讨论】:
谢谢。我的数据库看起来有点不同。我试图调整代码以适应我的数据库的外观,但我得到 Thread 1: signal SIGABRT 错误,所以它没有找到孩子。你看到我没有看到的任何错误吗?我的数据库如下所示: People Random User ID Code DataPoin 1: DataPoin 2 : Coordinates + latitude: ...... longitude: ..... Random User ID Code2 ........问题,因为这里太长了: 5 分钟评论限制刚刚达到。问题中的数据库结构比评论中的更清晰。 @noname87f 您需要将坐标节点作为子快照读取。我更新了我的问题来解决这个问题。 非常感谢。我很感激你的时间。我的数据库中没有“名称”路径,所以我删除了它。我仍然在 let lat = ... 行出现错误。但是,上一行 let coordSnap 可以工作,所以 this 的形式是正确的。我不知道这是否是因为纬度和经度不是坐标的正常孩子,而是它的双重列表。您对为什么会出现错误有任何想法吗?我已经在问题中添加了我现在使用的代码。 @noname87f 我将该代码从一个有效的现有项目中取出。我的猜测是您没有指定正确的子密钥名称。我的结构包括子键Latitude
,因此我的代码访问了子键Latitude
。您的结构包括latitude
(小写L),所以这是您应该访问的孩子。我的代码匹配 my 结构,因此您可能需要匹配 your 结构。我添加了阅读 name
节点作为模板,以便您了解如何访问其他子节点。有意义吗?以上是关于一旦坐标在 Firebase 中保存为字符串,如何在 CLLLoationDegrees 中获取它们来计算用户之间的距离?的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有 Geofire 的情况下将位置对象保存在 Firebase 中?
如何将查询中的数据保存在字符串数组中,Firebase iOS?