Не удается обновить значение узла в узле childAutoId для обновления значений словаря

Я работаю над приложением для отслеживания веса, когда я добавляю новые данные в 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)

             }
         }
     }
 }

Не удается обновить значение узла в узле childAutoId для обновления значений словаря

Почему бы вам не использовать только один дочерний уровень с автоматическим идентификатором после WeightTracker? Я вижу, что вы добавляете данные в WeightTracker > child(id) > childAutoId > data. Но когда вы хотите обновить данные, вы делаете WeightTracker > child(id) > data. Если вы хотите сохранить свою структуру, вам необходимо получить доступ к WeightTracker > child(id) > childAutoId > data, если вы хотите переопределить значения этих двух ключей (date и weight).

denis_lor 22.05.2019 14:48

можешь ли ты показать мне ? буду очень благодарен.

ronak jani 22.05.2019 14:51

Чего бы вы хотели добиться, выполняя ДОБАВИТЬ НОВУЮ ЗАДАЧУ и ОБНОВИТЬ ЗАДАЧУ? Как вы ожидаете, что ваша структура будет выглядеть в firebase?

denis_lor 22.05.2019 14:55

когда я добавляю новую задачу, если дата новая, тогда будут добавлены новые данные, и если я добавлю новые данные к существующей дате, данные будут обновлены.

ronak jani 22.05.2019 14:58

как на картинке, если моя дата "19.05.2019". а затем я ввожу вес до этой даты, только вес будет обновлен.

ronak jani 22.05.2019 15:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В этом примере вы можете сделать 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-й строке функции.

ronak jani 22.05.2019 15:39

я попытался показать «Ярлыки аргументов» (из:, с:) «не соответствуют доступным перегрузкам», эта ошибка, сэр.

ronak jani 22.05.2019 16:03

@ronakjani Извините, раньше я был недоступен. Я просто нашел время и обновил свой первоначальный ответ из-за опечатки, из-за которой ошибка «Ярлыки аргументов» исчезла. Вы можете повторить попытку?

denis_lor 22.05.2019 23:16

Чтобы найти решение, давайте сначала определим проблему.

Вот ваша структура

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)
    })
}

Единственная проблема со вторым методом заключается в том, что запрос не вернет результатов, если дата не существует, поэтому вы должны убедиться, что она существует, прежде чем выполнять обновление.

Другие вопросы по теме