现在我有 .observeSingleEvent(of: .value)
将我所有的注释加载到 map 上:
func loadAnnotations() {
if let uid = Auth.auth().currentUser?.uid {
uidRef.child(uid).child("annotations").observeSingleEvent(of: .value, with: { (snapshot) in
for item in snapshot.children {
// annotationListItem is a struct I created
let annotationItem = AnnotationListItem(snapshot: item as! DataSnapshot)
let doubleLatitude = Double(annotationItem.mapViewLatitude!)
let doubleLongitude = Double(annotationItem.mapViewLongitude!)
let coordinate = CLLocationCoordinate2DMake(doubleLatitude!, doubleLongitude!)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = annotationItem.annotationTitle
annotation.subtitle = annotationItem.annotationSubtitle
self.mapView.addAnnotation(annotation)
}
}, withCancel: nil)
}
}
现在我希望 map 在每次用户添加新注释时更新,所以我输入了完全相同的代码,但使用了 .observe(.childAdded)
func annotationChildAdded() {
if let uid = Auth.auth().currentUser?.uid {
uidRef.child(uid).child("annotations").observe(.childAdded, with: { (snapshot) in
for item in snapshot.children {
let annotationItem = AnnotationListItem(snapshot: item as! DataSnapshot)
let doubleLatitude = Double(annotationItem.mapViewLatitude!)
let doubleLongitude = Double(annotationItem.mapViewLongitude!)
let coordinate = CLLocationCoordinate2DMake(doubleLatitude!, doubleLongitude!)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = annotationItem.annotationTitle
annotation.subtitle = annotationItem.annotationSubtitle
self.mapView.addAnnotation(annotation)
}
}, withCancel: nil)
}
}
我得到的错误是:
无法将类型“__NSCFString”(0x1060b84f0)的值转换为“NSDictionary”(0x1060b92d8)。 snapshotValue 打印说明: ([String : AnyObject]) snapshotValue = 变量不可用>
我该如何解决这个问题?
更新
.observe(.value)
有效。但我仍然想知道为什么 .childAdded
没有
最佳答案
这里的问题是 .observeSingleEvent(of: .value)
和 .observe(.childAdded)
不返回相同的东西。
当您调用 .observe(.value)
时,它会返回整个节点,其中包含事件发生时的所有内容。
但是,当您使用 .observe(.childAdded)
时,它只会返回添加到指定路径的内容(即添加的子项)。
您可以通过在这两种方法中执行 print(snapshot)
来看到这一点,您将很容易看出差异。
因此,要使用 .childAdded 访问您的数据,您不需要像使用 .observeSingleEvent(of: .value) 那样遍历所有子项。相反,你会这样做:
guard let uid = Auth.auth().currentUser?.uid else {
return
}
uidRef.child(uid).child("annotations").observe(.childAdded, with: { (snapshot) in
let annotationItem = AnnotationListItem(snapshot: item as! DataSnapshot)
let doubleLatitude = Double(annotationItem.mapViewLatitude!)
let doubleLongitude = Double(annotationItem.mapViewLongitude!)
let coordinate = CLLocationCoordinate2DMake(doubleLatitude!, doubleLongitude!)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = annotationItem.annotationTitle
annotation.subtitle = annotationItem.annotationSubtitle
self.mapView.addAnnotation(annotation)
}
})
此外,我不建议您像那个item as 那样强制转换您的元素! DataSnapshot
因为如果您遗漏了数据库中的某些内容,应用程序就会崩溃。
相反,我会这样做,使用 guard 语句:
guard let uid = Auth.auth().currentUser?.uid else {
return
}
uidRef.child(uid).child("annotations").observe(.childAdded, with: { [weak self] (snapshot) in
let annotationKey = snapshot.key
guard let longitude = snapshot.childSnapshot(forPath: "longitude").value as? NSNumber else { return }
guard let latitude = snapshot.childSnapshot(forPath: "latitude").value as? NSNumber else { return }
guard let title = snapshot.childSnapshot(forPath: "title").value as? String else { return }
// Here it really depends on how your database look like.
// ...
// Create your annotation item using the values from the snapshot :
let annotation = AnnotationListItem(id: annotationKey, title: title, longitude: longitue, latitude: latitude)
// Finally add the data to an array :
self?.annotationsArray.append(annotation)
// Or directly to your mapView :
self?.mapView.addAnnotation(annotation)
})
如果有帮助请告诉我;D
更新
例如,假设您的数据库中最初有 3 个子节点。它会做类似的事情:
初始:观察者被调用:
你得到 child 1
你得到 child 2
你得到 child 3
现在,如果添加另一个 child :
新 child :观察者被调用:
你得到 child 4
等..
关于swift - .oberve(.childAdded) 产生错误,而 .observeSingleEvent(: . 值)不是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46214627/