Я работаю над приложением для отслеживания веса, когда я добавляю новые данные в firebase, оно работает правильно, но когда я обновляю данные с этой даты, новые данные добавляются с существующим уникальным идентификатором электронной почты. Я хочу обновить текущий вес дат, если я добавлю вес снова в этот день [черный круг, показывающий, где я хочу обновить вес, а оставшиеся другие данные - это то место, где обновляются фактические данные
вот и мой код тоже.
@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)
}
}
}
}
можешь ли ты показать мне ? буду очень благодарен.
Чего бы вы хотели добиться, выполняя ДОБАВИТЬ НОВУЮ ЗАДАЧУ и ОБНОВИТЬ ЗАДАЧУ? Как вы ожидаете, что ваша структура будет выглядеть в firebase?
когда я добавляю новую задачу, если дата новая, тогда будут добавлены новые данные, и если я добавлю новые данные к существующей дате, данные будут обновлены.
как на картинке, если моя дата "19.05.2019". а затем я ввожу вес до этой даты, только вес будет обновлен.
В этом примере вы можете сделать 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
исходит из текстового поля пользовательского интерфейса и учитывается.
Функцию также можно сделать более осмысленной для чтения, разделив некоторые действия на экземпляры переменных и повторно используя их следующим образом:
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)
})
}
}
показывает эту ошибку «Невозможно определить тип закрытия в текущем контексте» в 7-й строке функции.
я попытался показать «Ярлыки аргументов» (из:, с:) «не соответствуют доступным перегрузкам», эта ошибка, сэр.
@ronakjani Извините, раньше я был недоступен. Я просто нашел время и обновил свой первоначальный ответ из-за опечатки, из-за которой ошибка «Ярлыки аргументов» исчезла. Вы можете повторить попытку?
Чтобы найти решение, давайте сначала определим проблему.
Вот ваша структура
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)
})
}
Единственная проблема со вторым методом заключается в том, что запрос не вернет результатов, если дата не существует, поэтому вы должны убедиться, что она существует, прежде чем выполнять обновление.
Почему бы вам не использовать только один дочерний уровень с автоматическим идентификатором после WeightTracker? Я вижу, что вы добавляете данные в
WeightTracker > child(id) > childAutoId > data
. Но когда вы хотите обновить данные, вы делаетеWeightTracker > child(id) > data
. Если вы хотите сохранить свою структуру, вам необходимо получить доступ кWeightTracker > child(id) > childAutoId > data
, если вы хотите переопределить значения этих двух ключей (date
иweight
).