现在我有.observeSingleEvent(of: .value)
将我的所有注释加载到地图上:
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)
}
}
现在我希望每次用户添加新注释时都会更新地图,因此我使用.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
没有
答案 0 :(得分:0)
这里的问题是.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 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个子节点。它会做那样的事情:
initial:观察者被调用:
你得到孩子1
你得到孩子2
你得到孩子3
现在,如果添加了另一个孩子:
新孩子:观察者被召唤:
你得到孩子4
等。