当我向Firebase添加新数据时,我正在使用体重跟踪应用程序,它可以正常工作,但是当我从该日期开始更新数据时,新数据将与现有电子邮件的唯一ID相加,我想更新当前日期的体重我在那一天再次增加体重 [黑色圆圈显示我要更新权重,其余其他数据是实际数据正在更新
这也是我的代码。
@IBAction func addButton(_ sender: UIButton) {
let time = Date()
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
let formatteddate = formatter.string(from: time as Date)
if formatteddate == addDate.text!{
self.UpdateTaskWithName(name: addWeight.text!, date: addDate.text!) { (success) in
print("**** TASK UPDATED *******")
DispatchQueue.main.async {
self.navigationController?.popViewController(animated: true)
}
}
}else{
if let text = self.addWeight.text{
if let date = self.addDate.text{
self.saveTaskWithName(name: text, date: date, completionHandler: { (success) in
print("**** NEW TASK ADDED *******")
DispatchQueue.main.async {
self.navigationController?.popViewController(animated: true)
}
})
}
}
}
}
func saveTaskWithName(name:String,date:String, completionHandler:@escaping ((_ success:Bool)->Void)){
let dict = ["weight": name, "date" : date] as [String : Any]
if let userid = Auth.auth().currentUser?.uid{
self.ref.child("WeightTracker").child(userid).childByAutoId().setValue(dict) { (error, reference) in
if let err = error{
print(err.localizedDescription)
}else{
// data save successfully
completionHandler(true)
}
}
}
}
func UpdateTaskWithName(name:String,date:String, completionHandler:@escaping ((_ success:Bool)->Void)){
let dict = ["weight": name, "date" : date] as [String : Any]
if let userid = Auth.auth().currentUser?.uid{
self.ref.child("WeightTracker").child(userid).updateChildValues(dict) { (error, reference) in
if let err = error{
print(err.localizedDescription)
}else{
// data save successfully
completionHandler(true)
}
}
}
}
答案 0 :(得分:1)
在此示例中,您可以执行query
来查找node
,其中您的日期与您希望更新的日期相匹配。该查询会将key
返回到节点(用于childByAutoId
节点),您可以使用该节点更新子节点weight
:
func UpdateTaskWithName(name:String, date:String, completionHandler:@escaping ((_ success:Bool)->Void)){
if let userid = Auth.auth().currentUser?.uid {
self.ref.child("WeightTracker")
.child(userid)
.queryOrdered(byChild: "date")
.queryEqual(toValue: date)
.observeSingleEvent(of: .value, with: { snapshot in
self.ref.child("WeightTracker").child(userid).child(snapshot.key).child("weight").setValue(name)
})
}
}
考虑到name
是指date
来自UI TextField并进行考虑,这就是函数的样子。
通过将一些动作拆分为变量实例并像这样重新使用它们,还可以使该函数的读取更有意义:
func UpdateTaskWithName(name:String, date:String, completionHandler:@escaping ((_ success:Bool)->Void)){
if let userID = Auth.auth().currentUser?.uid {
let userIDRef = self.ref.child("WeightTracker").child(userID)
let query = userIDRef.queryOrdered(byChild: "date").queryEqual(toValue: date)
query.observeSingleEvent(of: .value, with: { snapshot in
let childByAutoIDNodeKey = snapshot.key
let refToUpdate = userIDRef.child(childByAutoIDNodeKey).child("weight")
refToUpdate.setValue(name)
completionHandler(true)
})
}
}
答案 1 :(得分:0)
要找到解决方案,我们首先确定问题所在。
这是您的结构
Weighttracker
user_uid_0
child_by_auto_id_0
date: "19.05.2019"
weight: "236"
假设您要更新该日期的体重,这是您的更新代码
self.ref.child("WeightTracker").child(userid).updateChildValues(dict)
请记住,在使用updateChildValues时,如果它们不存在,则会添加它们。这是您在以下位置更新这些子值的代码的路径
WeightTracker/uid/values being updated here
当你想要的时候
WeighTtracker/uid/childByAutoId/values being updated here
^^^^^^^^^^^^^
问题在于您不知道childByAutoId是什么,因此您无法直接更新该数据。
有两种解决方案;一种是使用日期作为节点的键,这意味着您的结构将需要更改
WeightTracker
user_uid_0
20190519
weight: "236"
然后更新变得简单
let userid = Auth.auth().currentUser.uid
let pathRef = self.ref.child(WeightTracker).child(userid).child(date)
pathRef.child("weight").setValue(weight)
使用现有结构的另一种选择是查询日期等于所需日期的节点,然后获取该节点的密钥,然后更新子权重节点
func updateViaQuery() {
let uid = //users uid
let uidRef = self.ref.child("WeightTracker").child(uid)
let query = uidRef.queryOrdered(byChild: "date").queryEqual(toValue: "19.05.2019")
query.observeSingleEvent(of: .value, with: { snapshot in
let key = snapshot.key
let refToUpdate = uidRef.child(key).child("weight")
refToUpdate.setValue(weight)
})
}
第二种方法的唯一问题是,如果日期不存在,查询将不返回任何结果,因此您需要确保在进行更新之前这样做。